COMMENT \ FOONLY F2-F3 MICRO-CODE Recent history: 21 Mar 80 TVR Added DMOVE, DMOVEM and ADJSP instructions. Changed opcode of XMOVE to 107, as it conflicted with ADJSP. Experimental boot switches in preparation for auto-loading tapes. 22 Mar 80 TVR Fixed some typos with above. 26 Mar 80 TVR Added WAITS switch to modify pager to make references to user ACs go to user shadow memory (instead of special place pointed to by AC Base Register in BBN Pager). Since the addresses supplied to the random instructions must be larger than 17 to prevent references to ACs in 2901, a page was stolen from the EXEC address space, currently 770xxx, and that page table entry in the hardware is copied from entry 0 of the user page table in core. Also, for Stanford only, defined ILGIOT to reference the PAN interface, so that CONSZ will skip when no device is present and new devices can be added to that bus without microcode changes. Fixed dispatch for UUO0 to look at opcode field only. Made indirect dispatch test for the stop switch, so that stop will stop indirection loops Fixed DATAO PI, to page fault properly. 27 Mar 80 TVR Pager mods and tape hack for CCRMA were both buggy. Fixed. Fixed bug in pager: PC was being over-decremented on page fill cycle when indirection failed in XCTR'ed instruction. 29 Mar 80 TVR Flushed a spurious DEST-A-MEM which prevented WAITS from working at XCTAC+1. 02 Apr 80 TVR Added code to trap IOT references if not Exec or IOT-User mode. New macro, UIOTRP, jumps if in IOT-USER mode. ILGIOT still is a no-op for non-Stanford microcode for the moment. For Stanford only, the PAN interface has its micro-interrupts re-enabled on PI-CHECK-RQS. Bummed an instruction out of IOTDIS. Indirect bit is guaranteed zero so one can double by shifting instead of doing an add. 03 Apr 80 TVR Fixed ADJSP. XCT n,[PUSH x,y] failed if x was a user AC reference. Added code to emulate PUSH/POP. 04 Apr 80 TVR XCT 1,[POP x,AC] didn't have a chance of working. It gets emulated as well. Added code for KAFIX. 11 Apr 80 TVR Changed PAN interrupt enables in PI-CHECK-RQS. Added reset code and IOT dispatch for temp. Grinnell code (under STANSW). Looked at DIV code to try to fix divide-by-zero. Gave up in disgust. I won't touch that code with a 10 ft battle axe! Fixed another stupid typo in ADJSP. 22 Apr 80 TVR Fixed two bugs in DPB (and one in LDB). DPB sets half flag if it gets a page fault on the pointer reference. The monitor doesn't care much, but some user programs look at the fault PC and flags to decide what kind of Pager and CPU they are running under. The other bug was that in LDB and DPB; they do not handle bytes which 'wrap-around', i.e. 36-P with macro calls in order to use microcode memory in a more reasonable fashion. More comments added. 07 May 80 TVR The assembler is a loser! It redefines macros alright, some of the time. At any rate, the macros were rewritten and all (shudder) of the macro calls changed. 10 May 80 TVR Merged in the rest of the CCRMA changes. 11 May 80 TVR Grumble, curse, moan!!! No, the assembler isn't THAT bad. The REAL loser not the assembler, but the person who wrote oet the old version (which had a different name) onto SCI:SLOEXP.SAV and which contains various and sundry bugs, one of which appears to be macro re-definition and another being an unusable storage map. So, everything was delayed a week while i tried to get around bugs which had already been fixed. Fortunately, this time it could be converted back to the original form with the aid of a TECO macro. Adjusted memory usage and it now assembles except for re-usage of 5300 and 5301. 12 May 80 TVR Adjusted some of memory usage to make the silly thing assemble WAITS version in preparation for making larger adjustments. PAN interrupts are come out in the status word as low true. PAN interrupt code has been corrected for that. Fixed a rather obscure bug in SETHLF. Because SETHLF stores into CRYOV, the EXEC mode shift register (what COND[USER] is based on) gets forced to be the current space. Thus, page faults from User pages in Exec mode on certain instructions (like IDPB) were being processed as being Exec mode page faults. 13 May 80 TVR Added .QUAD macro and put it in places jumped to by SLOOP which were previously controlled by :. Adjusted memory usage to make the one area using .QUAD fit. Fixed misfeature in experimental boot. LDB/DPB for bytes that wrap around just isn't right at all! BYTE-OVERF is condition BEFORE incrementing, not after. So, i will have to rethink this one to come up with something that handles that case properly without slowing byte instructions down significantly. Changes at CCRMA follow: 15 May 80 TVR Fixed bug in DMOVNM. Changed mechanism for PAN interrupts. The PAN microinterrupt enable is turned off when the interrupt for that channel is recieved and turned on by PI-CHECK-RQS by setting all of the microinterrupt enables for the PAN to the complement of PI IN PROGRESS and PI REQUEST. This means that the PAN can only request interrupts whenever something else isn't using those channels. This implies that any PAN devices must be on the end of CONSZ chains, or else they will steal interrupts from other, interrupt counting devices. 24 May 80 TVR Grinnell interrupt bug fixes. Starting putting names on opcodes and stuff to make it easier to use with E. 26 May 80 TVR Fixed problem in JRST1+1 falling thru to nothingness. A few more editorial changes. 07 Jul 80 TVR Changed CONO APR, code to turn on AR INT ENB and also made symbols some references to APR A-MEM relating to APR. Fixed bugs in F2 version of overflow interrupt. *** Did not look at F3 code for same. *** More comments added. 08 Jul 80 TVR Made attempt to fix [I]DIV by zero and no divide. As part of that, commented the setup part of DODIV, and added code to try to restore AC after finding no divide case. I'm not sure the DIV case will work properly, but we'll see... Fixed bug in FDVR of negative number which set the flags wrong. It had the wrong MASK when complementing a negative dividend exponent. Many comments added to divide and KA floating point as a result of chasing these. Some have (???) being i'm not sure that either the code and/or the comments are right. 15 Jul 80 TVR Installed LPT device. Microcode for LPT is still being tested. Fixed bug in PAN enabling, so that PI channels that are not turned on do not have their micro interrupts enabled. 22 Jul 80 TVR Fixed bug in [I]DIV which clobbered PC on divide by zero. Sets overflow on KIFIX now. Also, sets overflow on KAFIX, which should not cause any problems. 25 Jul 80 TVR Added FIXR and FLTR. 23 Aug 80 TVR Fixed bugs in LDB/DPB having to do with bytes which overflow word boundaries. Ran out of micro-code space and re-adjusted .USEs to recover some wasted space. More work on LPT device. 20 Sep 80 TVR Added a new switch, MUM2. At the moment, this only causes ECC logging information to go to 1776x instead of 0776x. Under WAITS switch, changed APR CONI, and clock interrupt decision, to implement special feature of SAIL's KA, which turns on bit 27 in APR CONI when it is NOT interrupting. 25 Sep 80 TVR Began merge of CCRMA version with DWP version. MUM2 became XUCODE. Tape code got moved to separate files in order to make SRCCOM feasible. New symbol TYMORG defines where absolute part of TYMNET code is assembled. It only need be changed in the future. Changes at Foonly follow: 15 Aug 80 BO Added Versatec to unused half of CTY IOT dispatch, device code 124. Removed the 16 NOP's at the very end of memory. VC code is broken up to fit available space. Used absolute locations 5340-5437 (5340 defined as VCORG1) and 7733-7777 (VCORG2) defined in VC.SLO 25 Sep 80 TVR Following changes were not documented but evident from source comparison: MASK[18] was added to dispatch code at 2002. Presumably, this done to make the interrupt bug trap work properly. CONSZ to DLS when no code is assembled now always skips, so that TENEX can tell if the DLS exists. New device, VID, added. This is Gossett's new display. uDevice numbers for the DLS, VC are now variables. Code for DMA tape controller was added. Two new switches were added, OTP and NTP, which stand for Old Tape and New Tape controllers. NTP is for the DMA tape controller and all others are OTP. Changes to CTY code and TYMNet code to account for differences in MAPF fields for new tape controller. Some adjustment of .ORG and .USE were done to make things fit. FDVL was fixed. This involved making changes to A-MEM usage in floating divide code. SLOEXP was modified to truncate jump addresses to 12 bits without complaint. New switch, XUCODE, was added. If XUCODE=1, then some I/O devices are assembled into the upper 4K of microcode memory. A new macro, .GETADR(X), constructs a 12 bit number in Q. Tape code is optionally moved into upper 4K of microcode memory if XUCODE=1. Dispatches for tape code were moved. Versions merged. This version is designated 1.02 by fiat of TVR. 25 Sep 80 TVR Completed merge. *** VC needs a new device code. It had used the slot assigned historically to the LPT. Some other minor formatting/comment changes were made to make the source merge program work properly. There were strong differences between the two in the floating divide code. Hopefully, all of the A-MEM changes made it across. I have checked them by hand. 26 Sep 80 TVR Assigned device 520 to VC (Versatec interface), and modified VC.SLO to accomdate that. 4 Nov 80 PG Added new display service for FooVision (VID.SLO). This stuff makes use of high memory, since it is quite large. Note that the ,INSERT must be right after the tape code, since (due to kludgery) .USE[OTHER] doesn't work properly for getting you back to low memory (see TYMFOO). For your information: .USE[HIGHMEM] gets you to high memory .USE[OTHER] gets you back to low memory GETADR[FOO] JUMP[GOHIGH] $ jumps to high memory 10000+FOO (Note that this expands to 2 microcode words.) JUMP[GOMAIN] $ jumps to MAIN in low memory 21 Nov 80 - PG Added new output instruction to TYMNET for F5 diagnostics. Takes the data in the effective address, using the right 16. bits of the right half as data to go out; AC=1 => STB DATA, and AC=2 => STB CTRL. Above is version 55 as received at Symbolics 16 Mar 81 Moon Moved TYMNET code into separate file, added new file DR11 under new switch DR11P providing packet oriented DR11C support. Involves new version of SWINIT also. 19 Mar 81 Moon Moved DLSINI macro into F2X and F2SYM files. This is the macro that defines the initial line speeds and characteristics. 21 Mar 81 Moon Removed setting of TNODIBN etc. from CFDEF since having these as definitions in the ROT field stimulates all sorts of bugs in the microassembler. Made them ordinary symbol definitions separately in both the TYMNET and DR11 files. 31 Mar 81 Moon Made XCT 3,[LDB x,[foo(xr)]] get xr from the previous context. Also turned off Foovision in the Symbolics version of the microcode, since it takes forever to assemble and we don't have one. 24 Apr 81 Moon Merged Poole's recent changes: Fix pdl overflow to work correctly with page faults by setting a bit in the PC and checking for it in the main loop, rather than setting a bit in the APRSTS then signalling an interrupt which can easily get lost if there is a page fault. Add "WK" and "IMP1" include files. Make byte-pointer indirection loops interruptible. Don't increment counters in locations 30-32 of events having to do with the map. I guess this is supposed to be an efficiency improvement. 28 Apr 81 Moon Also fix typos at APRCK1 and APRCII, testing wrong bit in APRSTS for pdl-overflow. 1 May 81 Moon Fix HSMAIN+1 to use correct MAPF field so that HLRZS at the end of a page does not sometimes get executed twice. 3 June 81 Moon Fix bug introduced by Poole's changes for pdl overflow. JRST 4, in user mode loops forever because instruction after JRST9 was spuriously deleted. Also added some comments to this bletcherous JRST microcode and removed an instruction that didn't do anything (JUMP[JRST4]). (End history) \ COMMENT \ ******************************************************** USEFUL MICROCODE WORD DEFINITIONS ******************************************************** \ F3SW = 1 - F2SW OTP = 1 - NTP FIXM1 = ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[NORM-RD] CYLEN[FIXM] $ FIXML = ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[NORM-RD] CYLEN[LONG] $ FIXM2 = ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-WRT] MAPF[NORM-WRT] CYLEN[FIXM] $ FIXM0 = ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[0] CYLEN[FIXM] $ .DEFINE MEMST [] [COND[-MA-AC] LBJUMP[MSMAIN] NORM ] ; NOTE: BECAUSE OF XCT MAPPED, MEMST IS SAME AS MEMSTMA ; .DEFINE MEMST [] [COND[-MA-AC] LBJUMP[SMAIN] NORM ] .DEFINE MEMSTMA [] [COND[-MA-AC] LBJUMP[MSMAIN] NORM ] DOSKIP = D[PC] ALU[D+1] DEST[MA PC] JUMP[MAIN1] NORM $ DONTSKIP = DEST[MA] SPEC[MA_PC] JUMP[MAIN1] $ DOJUMP = D[IR] DEST[MA PC] JUMP[MAIN1] NORM $ DOM1 = SPEC[MA_PC] JUMP[MAIN1] NORM $ CLRR = ROT 22 D[MASK 22] ALU[D&AC] ACSEL[AC] DEST[AC] $ CLRL = D[MASK 22] ALU[D&AC] ACSEL[AC] DEST[AC] $ ;SLFFXM - Self FIXM (?) ;Finish read fetch of read-modify-write type cycle. ;Check to make sure effective address is writable. ;Jump if AC field in IR is non-zero .DEFINE SLFFXM[ JDST ] [ ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-WRT] MAPF[NORM-WRT] CYLEN[FIXM] COND[-AC=0] JUMP[ JDST ] $ ] ;;;;;;APR-A-MEM DEFINITIONS -- THERE SHOULD BE 7 MORE OF THESE ! A-MEM-ECC-DATA = 1 ;Data on last ECC error -- readable by op. 750 ;;;;;;; BADLOC = JUMP[MAIN] $;NOP FOR NOWJUMP BADPC $ ;FOR WORDS WE SHOULDN'T USE ;;;;;ILGIOT = NORM JUMP[2000] $ ;The standard case for IOTs without devices .REPEAT 1 - STANSW [ .DEFINE ILGIOT[ ] [ JUMP [MAIN] ] ];.REPEAT 1 - STANSW ;At Stanford, any devices we don't know about go to the PAN interface. It ;may have something plugged into it that will respond to that address in a ;PDP-10ish manner. .REPEAT STANSW [ .DEFINE ILGIOT[ ] [ COND[-USER] LBJUMP[PANIOT] NORM ] ];.REPEAT STANSW ;Jump not IOT-USER mode .DEFINE UIOTRP[ XXX ] [ D[PC] ROT[6 + 1] MASK[1] COND[OBUS=0] JUMP[XXX] $ ];DEFINE .DEFINE GETADR[ADR] [ ;Place the 12-bit value of ADR in Q. D[CONST (77 & (ADR / 100))] ROT[6] DEST[Q] NORM $ ;High-order 6 bits D[CONST (ADR \ 100)] ALU[DORQ] DEST[Q] C600 ] ;Low-order 6 bits ;NOTICE that a "$" is REQUIRED after a call of GETADR. UUOLOC = D[CONST 40] JUMP[UUO1] NORM $ .DEFINE MUUO1 [][ D[PC] DEST[Q AR] JUMP[MUUO2] NORM $ ] .DEFINE UAOP1 [][ D[PC] DEST[Q AR] JUMP[UAOP] NORM $ ] SET-TEMP-USER = D[CONST 17] ROT[11] DEST[MAP-EXEC-SR] NORM $ SET-TEMP-EXEC = D[CONST 0] ROT[11] DEST[MAP-EXEC-SR] NORM $ ; ; THESE OUTLANDISHLY EXPLICIT DEFINITIONS OF NOP ASSURE THAT THE ; DECODER WILL PRINT 'NOP' ONLY WHEN YOU REALLY MEAN IT. ; NOP = COND[0] DEST[0] CONT ALU[D] ACSEL[AC] NO-MA-STB NO-AR-STB ROT[0] MASK[-1] ALU-D[NONE] $ DONOP = COND 0 DEST[ 0] ALU[D] ROT[0] MASK[-1] ACSEL[AC] JUMP[MAIN] ALU-D[NONE] NORM $ DODISP = D[MEM] DEST[IR-ALL MA AR] SPEC[PC+1-IF&] DISP[2374] CYLEN[DISP] $ ;------------------------------------------------------------------------------ ; ; CPU special registers uDevice 0 ; ;------------------------------------------------------------------------------ ; ; Dev Subsel Read Write ; ; 0 1 Address Break Register ; 2 Data switches Data lights ; 4 Address and console switches Clear latched switches (no data) ; 10 PC History (unimplemented) Set AR,ECC enables, MAP ON, etc. ; ; 1 1 ECC status ; 2 MAP status MAP (address in MA, LOCAL USER) ; 4 (Same as 1) ; 10 (Same as 1) ; ;------------------------------------------------------------------------------ ; ; A-Mem usage uDevice 0 & 1 ; (Note: Not all references are symbolic as yet. ; ;------------------------------------------------------------------------------ ;Device 0 A-MEM-ECC-DATA = 1 ;Data on last ECC error -- readable by op. 750 APRSTS = 2 ;Firmware status bits for APR APRENB = 7 ;Used to save ECC,AR interrupt enables, MAP ON, etc. during map ;trap processing ;Device 1 ECCSVP = 3 ;Pointer to next place to remember ECC interrupt in microcode ;memory COMMENT \ ***************************************************** REAL CODE ***************************************************** \ INST-DISP = 2000 ;Address of instruction dispatch. NORMAL = 4001 ;Assembly starts here .REPEAT XUCODE [ HIGHMEM = 10001 ;Upper 4K of 8K u-mem. ] ;**** Next macro blows up with multiply defined symbol. ;**** Note that it usually does not complain!!! .OPCODE[000]; UUO 0 COMES HERE (ALONG WITH UUO 1 - 7 ) NORM JUMP[UUO0-7] $ ;; Location 2001 is used elsewhere !!! .REPEAT F3SW [ ; INDIRECTING TRAPS HERE : 2002 ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[1] CYLEN[FIXM] $ D[MEM] DEST[IR-23 MA AR] DISP[2000] SPEC[PC+1-IF] CYLEN[DISP] $ ;STOP SWITCH, OV, & ECC TRAPS HERE (4 & 5) : 2004 DEST[CLR-DEV-FROM-INTR] JUMP[SOED] NORM $ : 2005 DEST[CLR-DEV-FROM-INTR] JUMP[SOED] NORM $ ; INDEXING TRAPS HERE : 2006 ALU[IX+D] D[IR] MASK[18.] DEST[AR IR-ADR MA] DISP[2000] SPEC[PC+1-IF] CYLEN[DISP]$ ;INTERRUPTS TRAP HERE : 2007 D[10] SDISP C600 $ .REPEAT 0 [ : 2007 JUMP[7740] $ : 7740 D[10] MASK[18.] DEST[Q AR] C550 $ D[CONST 21] ROT[6] ALU[D#Q] DEST[Q] C550 $ D[CONST 30] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 34] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 41] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 50] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 56] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 1] ROT[6] ALU[D#Q] DEST[Q] C550 $ D[CONST 62] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[AR] DEST[CLR-DEV-FROM-INTR] JUMP[.] C550 $ INTOK: D[10] SDISP C600 $ ] ;REPEAT 0 ] .REPEAT F2SW [ .REPEAT 0 [ : 2002 ;I/O INTERRUPTS TRAP HERE JUMP[7740] $ : 7740 D[10] MASK[18.] DEST[Q AR] C550 $ D[CONST 21] ROT[6] ALU[D#Q] DEST[Q] C550 $ D[CONST 30] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 34] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 41] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 50] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 56] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[CONST 1] ROT[6] ALU[D#Q] DEST[Q] C550 $ D[CONST 62] ALU[D#Q] COND[OBUS=0] JUMP[INTOK] C550 $ D[AR] DEST[CLR-DEV-FROM-INTR] JUMP[MAIN] C550 $ INTOK: D[10] SDISP C600 $ ];1 - DLS 9 JAN 80 BO :2002 ;I/O INTERRUPTS TRAP HERE D[10] SDISP C600 $ ;Just dispatch to ucode intrpt. routine for device. : 2003 ;STOP SWITCH TRAPS HERE DEST[CLR-DEV-FROM-INTR] JUMP[STOPS] NORM $ : 2004 ;CAN'T GET HERE FROM THERE... JUMP[.] $ ;HANG FOR NOW. : 2005 ;ECC ERRORS TRAP HERE DEST[CLR-DEV-FROM-INTR] JUMP[SECCS] NORM $ : 2006 ;PC OV TRAPS HERE ;;; DEST[CLR-DEV-FROM-INTR] JUMP[SOVRS] NORM $ D[CONST 1] DEST[DEV-ADR] JUMP[SOVRS] NORM $ ;Start setting up to read AR enabling : 2007 ;BOTH ECC AND OV (AT THE SAME TIME) TRAPS HERE DEST[CLR-DEV-FROM-INTR] JUMP[SECCS] NORM $ : 2010 ;NORMAL INDIRECT TRAPS HERE ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[1] CYLEN[FIXM] $ D[MEM] DEST[IR-23 MA AR] DISP[2374] SPEC[PC+1-IF] CYLEN[DISP] $ ;WHEN EXTEND HAPPENS, DISP[2176]? NO-- HOW WOULD WE SEE ;EXTENDED AREA OF IX REG? ;Changed from 2174 to 2374 to allow stop switch to stop ;indirection loops. TVR-Mar80 : 2012 ;NORMAL INDEXING TRAPS HERE ALU[IX+D] D[IR] MASK[18.] DEST[AR IR-ADR MA] DISP[2024] SPEC[PC+1-IF] CYLEN[DISP]$ ;WHEN EXTEND HAPPENS, DISP[2026] : 2014 ;EXTENDED INDIRECT TRAPS HERE ; SOMETHING MAKES THIS DIFFERENT FROM 2010 -- MAYBE LOADING H.O. MA?? JUMP[.] $ ;FOR NOW ;;;ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[1] CYLEN[FIXM] $ D[MEM] DEST[IR-23 MA AR] DISP[2176] SPEC[PC+1-IF] CYLEN[DISP] $ : 2016 ;EXTENDED INDEXING TRAPS HERE JUMP[.] $ ;FOR NOW ;;;D[AR] ROT[6] MASK[4] DEST[AC-SEL] NORM $ D[AR] ALU[D+AC] ACSEL[REG] DEST[IR-ADR MA AR] SPEC[PC+1-IF] DISP[2026] CYLEN[DISP] $ ] ;UUO1 UUO2 SMAIN SMAIN1 MAIN MAIN1 MAIN2 MSMAIN MSMAIN1 MUUO MUUO2 MUUO3 MUUO4 PIMUUO MUUO44 UUOPJ MUUO5X MUUO5Y UAOP AREA216 UMOVE JSYS JSYS3 ADJSP XMOVEM1 DMOVE DMOVN KIFIX DMOVEM DMOVNM FIXR FLTR UFA DFN FSC ;------------------------------------------------------------------------------ ; User UUO Trap ; ; Traps thru location 40 of the current space ; ; Instruction is stored in 40 (with effective address computed and ; index/indirection removed) ; Instruction in location 41 is executed, in the current space. It ; customarily either jumps, saving the PC and flags, or halts. ;------------------------------------------------------------------------------ .OPCODE[010] ;User UUOs 010:017 UUO1: D[CONST 40] DEST[MA] PUSHJ[UUOPJ] NORM $ ;Setup MA for trap area and make mask for removing index/indir. UUO2: D[IR] ALU[D&Q] DEST[MEMSTO] NORM $ ;Store instruction which caused trap. D[PC] ALU[D-1] DEST[PC] MAPF[MASTO] CYLEN[MEMSTO] $ ;Ordinary page fault if not writable. (*** Is PC correct???) ;Backup the PC to point at the offensive instruction D[CONST 41] DEST[MA] JUMP[MAIN1] NORM $ ;Execute contents of (same space) location 41, usually a JSR or ;a HALT instruction : 2024 SMAIN: ACSEL[MA] D[MEM] DEST[AC AR MA] SPEC[MA_PC] JUMP[MAIN1] NORM MAPF[STO] $ SMAIN1: D[MEM] SPEC[MA_PC] DEST[AR MA] JUMP[MAIN1] CYLEN[MEMSTO] MAPF[STO] $ MAIN: SPEC[MA_PC] DEST[MA] DEST[CLR-DEV-FROM-INTR] D[PC] ROT[9.] C600 COND[OBUS<0] JUMP[PDLTRP] $ ;START THE INSTR. FETCH, un-force DEV-ADR (from last intrpt.), ; and jump if a PDL OV is hanging. MAIN1: ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[1] JPOP[MAIN2] NORM $ MAIN2: D[MEM] DEST[IR-ALL MA AR] SPEC[PC+1-IF&] DISP[2374] CYLEN[DISP] $ .PAIR ;: 2032 ; .PAIR MSMAIN: ACSEL[MA] D[MEM] DEST[AC] JUMP[MAIN] CYLEN[MEMSTO] MAPF[MASTO] $ MSMAIN1: MAPF[MASTO] JUMP[MAIN] CYLEN[MEMSTO] $ AREA202 = . ;(Not a lot left) .OPCODE[020]; User UUOs 020-027 UUOLOC $ AREA204 = . .OPCODE[030]; User UUOs 030-037 UUOGO: UUOLOC $ AREA206 = . ;$*$*$*$ This should go somewhere else!!! .OPCODE[37] ;Set loc 2 wds. before MUUO (opcode 37 doesn't come here). ;We come here (from 2000) on opcodes 0-7. UUO0-7: D[IR] ROT[9.] MASK[9.] COND[OBUS=0] JUMP[MUUO] C550 $;J IF 0 UUO UUOLOC $ .OPCODE[040]; Monitor UUOs 040-047 (CALL,INIT,CALLI) MUUO: MUUO1 ;The following need not be contiguous with MUUO, it is merely here for clarity. ;It may be moved to another area if necessary. TVR-Apr80 ;------------------------------------------------------------------------------ ; Monitor UUO Trap ; ; Traps thru location 40 of the current space, typically to handle user ; request to the Monitor ; ; Instruction is stored in 40 (with effective address computed and ; index/indirection removed) ; Instruction in Monitor 41 is executed, in the Monitor space. It ; should save PC and flags, and handle the user's request. ;------------------------------------------------------------------------------ MUUO2: D[MASK 43] ROT[37] ALU[D&Q] DEST[CRYOV] NORM $ ;Clear USER D[CONST 40] DEST[MA] PUSHJ[UUOPJ] NORM $ ;Setup MA for trap area and make mask for removing index/indir. ; \ / ;Common code for instruction traps MUUO3: D[IR] ALU[D&Q] DEST[MEMSTO] NORM $ ;Store instruction which caused trap. D[MA] ALU[D+1] DEST[MA] CYLEN[MEMSTO] $ ;Now, get dispatch instruction ;------------------------------------------------------------------------------ ;*** CAUTION: If write fails, micro-machine hangs at 6100. This should be ;*** fixed when a more general page-fault mechanism is added. The ;*** best thing would be to just halt the macro machine. ;------------------------------------------------------------------------------ MUUO4: PIMUUO: D[CONST 55] ROT[2] DEST[Q FIXMAC-MAPF-RD] CYLEN[FIXM] $; JSR OPCODE ;TVR-Apr80: I don't have the foggiest notion what that FIXMAC ;is supposed to do here. The FIXM is needed for memory timing, ;but aren't we guaranteed not to be fetching from ACs here???? MUUO44: D[MEM] ROT[11] MASK[11] ALU[D#Q] COND[OBUS=0] JUMP[MUJSR] CYLEN[C650] $ ;Jump if trap instruction is a JSR (opcode 264 = 55*4) ALU[Q+1] DEST[Q] SHORT $ D[MEM] ROT[11] MASK[11] ALU[D#Q] COND[OBUS=0] JUMP[MUJSP] C550 $ ;Jump if trap instruction is a JSP (opcode 265) ALU[Q+1] DEST[Q] SHORT $ D[MEM] ROT[11] MASK[11] ALU[D#Q] COND[OBUS=0] JUMP[MUJSA] C550 $ ;Jump if trap instruction is a JSA (opcode 266) D[CONST 42] ROT[1] DEST[Q] SHORT $; JSYS OP D[MEM] ROT[11] MASK[11] ALU[D#Q] COND[OBUS=0] JUMP[MUJSYS] C550 $ ;Jump if trap instruction is a JSYS (opcode 104 = 42*2) D[PC] ALU[D-1] DEST[PC] SHORT $ ;Any other opcode will be XCTed and the regular code will ;resume. ;------------------------------------------------------------------------------ ;*** CAUTION: No special dispensation has been made for BLKI/BLKO. They ;*** MUST be handled specially, as if they DON'T skip, the ;*** second trap location should be executed and should be a JSR ;*** or some other instruction which saves flags. TVR-Apr80 ;------------------------------------------------------------------------------ D[AR] DEST[CRYOV] JUMP[MAIN2] $ ;Else restore flags and dispatch ;------------------------------------------------------------------------------ ;*** CAUTION: This probably will not work proper if reference is being made ;*** to EXEC memory and trap was from USER. What really needs to ;*** happen here is that the instruction should be XCTRed instead, ;*** It may be sufficient to SET-TEMP-EXEC. I haven't looked at ;*** the problem seriously. TVR-Apr80 ;------------------------------------------------------------------------------ ;Construct a mask which excludes indexing and indirection. Used by UUO trap ;routines (and currently no where else) UUOPJ: D[MASK 37] ROT[27] DEST[Q] POPJ NORM $ ;(NO SPACE IS LEFT. You will have plant jumps to another area to expand the ; above code!) .OPCODE[050]; Monitor UUOs 050-057 (OPEN,INIT,RENAME,IN,OUT) MUUO5X: D[IR] ROT[7] MASK[1] DEST[Q] NORM $ ;Special check for UUOs actually used by monitors we care about D[IR] ROT[10] MASK[1] ALU[D#Q] COND[OBUS=0] JUMP[MUUO] C550 $ ;Jump if UUO 50,51,56, OR 57 ALU[Q] COND[OBUS=0] JUMP[MUUO5Y] CYLEN[C450] $ ;Jump if 52 OR 53 ("Reserved for DEC") D[IR] ROT[11] MASK[1] COND[-OBUS=0] JUMP[MUUO] C550 $ ;Jump if 55 MUUO5Y: D[PC] DEST[Q AR] NORM JUMP[UAOP] $ ;Take illegal inst. trap. ;------------------------------------------------------------------------------ ; Illegal Instruction Trap ; ; Traps thru Monitor 60 ; ; Instruction is stored in 60 (with effective address computed and ; index/indirection removed) ; Instruction in Monitor 61 is executed, in the Monitor space. It ; should save PC and flags, and stop the offensive process. ;------------------------------------------------------------------------------ UAOP: D[MASK 43] ROT[37] ALU[D&Q] DEST[CRYOV] NORM $; CLR USER D[MASK 37] ROT[27] DEST[Q] NORM $ D[CONST 60] DEST[MA] JUMP[MUUO3] NORM $ AREA212 = . ;$*$** Stupid interrupt code makes this unusable! .OPCODE[060]; Monitor UUOs 060-067 ;(SETSTS,STATO,GETSTS,STATZ,INBUF,OUTBUF,INPUT,OUTPUT) MUUO1 $ ;;;AREA214 = . area214 = 2142 ;Sigh... Another fixed location .OPCODE[070]; Monitor UUOs 070-077 ;(CLOSE,RELEAS,MTAPE,UGETF,USETI,USETO,LOOKUP,ENTER) MUUO1 $ AREA216: .OPCODE[100]; UMOVE UMOVE: D[PC] ALU[D-1] DEST[MA PC] NORM $ ;RE-FETCH INSTR. FIXM1 JUMP[UMOVX] $ ;WAIT FOR FETCH. ; UMOVEI, UMOVEM, UMOVES .REPEAT 3 [ JUMP[UMOVE] NORM $ NOP $ ] .OPCODE[104]; JSYS JSYS: .REPEAT 1 - WAITS [ D[IR] ROT[33] MASK[11] COND[-OBUS=0] JUMP[JSYS1] C550 $; J IF NOT EX JSYS ];.REPEAT 1 - WAITS .REPEAT WAITS [ ;EX JSYS is disabled in WAITS' BBN pager. We simulate the same. JUMP[JSYS1] NORM $ ];.REPEAT WAITS JSYS3: D[PC] DEST[Q AR] JUMP[JSYS2] $; GET PC & FLAGS .OPCODE[105]; ADJSP ADJSP: D[IR] ROT[22] MASK[0] ALU[D+AC] SPEC[LEFT] DEST[Q] COND[OBUS<0] JUMP[ADJSP1] C550$ ;Jump if left result is negative D[IR] MASK[22] ALU[D+AC] DEST[AR] JUMP[ADJSP2] NORM $ ;Add right half ;(Continued just before TYMNET code) .OPCODE[106] ;XMOVEM ALU[AC] ACSEL[AC+1] DEST[HI-ABS-MA MA] NORM $ ALU[AC] DEST[MEMSTO] NORM JUMP[XMOVEM1] $ .USE[AREA204] XMOVEM1: ALU[0] DEST[HI-ABS-MA] NORM JUMP[MAIN] $ .OPCODE[107] ;XMOVE ALU[AC] ACSEL[AC+1] DEST[HI-ABS-MA MA] NORM $ ALU[0] DEST[HI-ABS-MA] JUMP[2401] NORM $ ;Illegal instructions (?) .REPEAT 113 - 110 + 1 [ UAOP1 $ NOP $ ] .REPEAT 1 - WK [ ;Illegal instructions (?) .REPEAT 117 - 114 + 1 [ UAOP1 $ NOP $ ] ] .REPEAT WK [ .OPCODE[114] NORM JUMP[WKSEND] $ NOP $ NORM JUMP[WKRCV] $ NOP $ NORM JUMP[WKSTAT] $ NOP $ D[CONST 24] DEST[DEV-ADR] NORM PUSHJ[WKRST] $ JUMP MAIN $ ] .OPCODE[120] ;DMOVE DMOVE: FIXM1 $ ; Fetch first word ACSEL[AC] D[MEM] DEST[AC] JUMP[DMOVE2] CYLEN[FIXM+1] $ ;Put it in an AC [*** Is CYLEN right? ***] ;(Continued just before TYMNET code) .OPCODE[121] ;DMOVN DMOVN: FIXM1 $ ;Fetch first word ACSEL[AC] D[MEM] ALU[NOTD] DEST[AC] SPEC[CRYOV] JUMP[DMOVN2] CYLEN[FIXM+1] $ ;Ones complement high order word. Set result flags ;(Continued just before TYMNET code) .OPCODE[122] ;KIFIX KIFIX: FIXM1 $ ;Fetch first word D[CONST 33] DEST[Q] JUMP[KIFIX1] NORM $ ;Start making magic constant ;(Continued just before TYMNET code) ;123 UAOP1 $ NOP $ .OPCODE[124] ;DMOVEM ;*** Note: Like on the KI10, DMOVEM AC,AC+1 will lose. DMOVEM: FIXM2 $ ; Make sure first word is in core ACSEL[AC] ALU[AC] DEST[MEMSTO] COND[-MA-AC] LBJUMP[DMOVM2] NORM $ ;Store first word. Decide where it really goes. ;(Continued just before TYMNET code) .OPCODE[125] ;DMOVNM ;*** Note: Like on the KI10, DMOVNM AC,AC+1 will lose. DMOVNM: FIXM2 $ ; Make sure first word is in core ACSEL[AC] ALU[NOTAC] DEST[AR] SPEC[CRYOV] JUMP[DMVNM2] NORM $ ;Ones complement high order word, leave result in IR ;(Continued just before TYMNET code) .OPCODE[126] ;FIXR FIXR: FIXM1 $ ;Fetch first word D[CONST 04] ROT[24.] DEST[Q] JUMP[FIXR1] NORM $ ;Start making constant 0.5 ;(Continued just before TYMNET code) .OPCODE[127] ;FLTR FLTR: FIXM1 $ ;Fetch first word D[MEM] DEST[AR] JUMP[FLTR1] $ ;Setup for normalize .OPCODE[130] ;UFA UFA: FIXM1 $ D[CONST 11] DEST[DEV-ADR] JUMP[UFA1] $ .OPCODE[131] ;DFN DFN: FIXM2 $ D[MEM] MASK[27.] ALU[0-D] DEST[AR] COND[OBUS=0] LBJUMP[DFN1] C600 $ .OPCODE[132] ;FSC FSC: D[MASK 27.] ALU[D&AC] ACSEL[AC] COND[OBUS=0] JUMP[FSCZAP] C550 $ ACSEL[AC] ALU[AC] DEST[AR] JUMP[FSC1] NORM $ ;IBP ILDB LDB IDPB DPB FAD FSB FMP FDV ;------------------------------------------------------------------------------ ; ; Byte Manipulation Instructions ; ;------------------------------------------------------------------------------ .OPCODE[133] ;IBP (and ADJBP) IBP: FIXM2 COND[HALF] JUMP[MAIN] $ ;A no-op if we're already incremented. D[MEM] DEST[Q AR] COND[AC=0] LBJUMP[IBP1] NORM $ ;Get byte pointer and decide if it's an ADJBP or a IBP .OPCODE[134] ;ILDB ILDB: FIXM2 $ D[MEM] DEST[Q AR] COND[-HALF] LBJUMP[ILDB1] NORM $ .OPCODE[135] ;LDB LDB: FIXM1 $ D[MEM] DEST[Q AR MA] COND[-MEM-IDX-IND] LBJUMP[LDB1] CYLEN[C500] $ IDPB: .OPCODE[136] ;IDPB FIXM2 $ D[MEM] DEST[Q AR] COND[-HALF] LBJUMP[IDPB1] NORM $ .OPCODE[137] ;DPB DPB: FIXM1 $ D[MEM] DEST[Q AR MA] LBJUMP[DPB1] COND[-MEM-IDX-IND] CYLEN[C500] $ ;------------------------------------------------------------------------------ ; ; Single Procession Floating Point ; ;------------------------------------------------------------------------------ ; ;FAD FADL FADM FADB FADR FADRI FADRM FADRB ; .OPCODE[140] ;Opcodes 140-147 FAD: FIXM1 JUMP[FAOS1] $ NOP $ FIXM1 JUMP[FAOS2] $ NOP $ FIXM2 JUMP[FAOS3] $ NOP $ FIXM2 JUMP[FAOS4] $ NOP $ FIXM1 JUMP[FAOS1] $ NOP $ D[MA] ROT[18.] DEST[HOLD] SPEC[LEFT] JUMP[FAOS5] NORM $ NOP $ FIXM2 JUMP[FAOS3] $ NOP $ FIXM2 JUMP[FAOS4] $ NOP $ ; ;FSB FSBL FSBM FSBB FSBR FSBRI FSBRM FSBRB ; .DEFINE FSBMAC[X] [ D[MEM] ALU[0-D] DEST[HOLD] JUMP[X] NORM ] .OPCODE[150] ;Opcodes 150-157 FSB: FIXM1 $ FSBMAC[FAOS1] $ FIXM1 $ FSBMAC[FAOS2] $ FIXM2 $ FSBMAC[FAOS3] $ FIXM2 $ FSBMAC[FAOS4] $ FIXM1 $ FSBMAC[FAOS1] $ D[MA] ROT[18.] DEST[HOLD] ALU[0-D] SPEC[LEFT] JUMP[FAOS5] NORM $ NOP $ FIXM2 $ FSBMAC[FAOS3] $ FIXM2 $ FSBMAC[FAOS4] $ ; ;FMP FMPL FMPM FMPB FMPR FMPRI FMPRM FMPRB ; .OPCODE[160] ;Opcodes 160-167 FMP: FIXM1 JUMP[FMP1] $ NOP $ FIXM1 JUMP[FMP2] $ NOP $ FIXM2 JUMP[FMP3] $ NOP $ FIXM2 JUMP[FMP4] $ NOP $ FIXM1 JUMP[FMP1] $ NOP $ D[MA] ROT[18.] DEST[HOLD] SPEC[LEFT] JUMP[FMP5] NORM $ NOP $ FIXM2 JUMP[FMP3] $ NOP $ FIXM2 JUMP[FMP4] $ NOP $ ;FDV FDVL FDVM FDVB FDVR FDVRI FDVRM FDVRB .DEFINE DIVMAC[X] [ D[CONST 11] DEST[DEV-ADR] JUMP[X] NORM ] .OPCODE[170] ;Opcodes 170-177 FDV: FIXM1 $ DIVMAC[FD1] $ FIXM1 $ DIVMAC[FD2] $ FIXM2 $ DIVMAC[FD3] $ FIXM2 $ DIVMAC[FD4] $ FIXM1 $ DIVMAC[FD1] $ D[MA] ROT[18.] DEST[HOLD] SPEC[LEFT] NORM $ DIVMAC[FD1] $ FIXM2 $ DIVMAC[FD3] $ FIXM2 $ DIVMAC[FD4] $ ;MOVE MOVE1 MOVEI MOVEM MOVES MOVS MOVSI MOVSM MOVSS MOVN MOVNI MOVNM MOVNS MOVM MOVM1 MOVMI MOVMM MOVMS MOVMS1 MOVMS3 MOVMS4 MOVMS5 MOVMS6 MOVMS2 ;------------------------------------------------------------------------------ ; ; MOVE Group ; ;------------------------------------------------------------------------------ .OPCODE[200] ;MOVE MOVE: FIXM1 $ ;Wait for memory, handle page faults, and fixup AC references MOVE1: ACSEL[AC] D[MEM] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] CYLEN[FIXM+1] $ ;Store result of read in AC ;Start next instruction fetch (DEST[MA] refers to SPEC[MA_PC]) ;We are referring to the AC specified by the AC field in the IR .OPCODE[201] ;MOVEI MOVEI: ACSEL[AC] D[IR] MASK[18.] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;Store effective address into AC ;Ignore any page faults or other memory related problems. Read ;will be ignored (except for ECC checking) ;Start next instruction fetch (DEST[MA] refers to SPEC[MA_PC]) ;We are referring to the AC specified by the AC field in the IR .OPCODE[202] ;MOVEM MOVEM: ACSEL[AC] ALU[AC] DEST[MEMSTO] MEMST $ ;Start writing AC (selected by AC field in IR) into memory. ;MEMST macro will send us to MSMAIN (if we're writing to ;another AC) or MSMAIN1 (if it's a real memory reference) ;to complete to store. .OPCODE[203] ;MOVES MOVES: FIXM1 COND[-AC=0] JUMP[MOVE1] $ ;If AC field (in IR) is non-zero, we treat this as if it ;were a MOVE instruction (a slight fudge). ;*** Shouldn't this be a FIXM2? Then it would do the right ;*** thing for the clever person trying to fetch and dirty ;*** a page. TVR-Apr80 D[MEM] DEST[MEMSTO] MEMST $ ;If AC field is zero, this is a no-op which writes memory. .OPCODE[204] ;MOVS MOVS: FIXM1 $ ACSEL[AC] D[MEM] ROT[18.] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] CYLEN[FIXM+1] $ ;Rotating by 18 swaps halves. Otherwise, it's just like a MOVE .OPCODE[205] ;MOVSI MOVSI: ACSEL[AC] D[IR] ROT[18.] DEST[AC MA] SPEC[LEFT&MA_PC] JUMP[MAIN1] NORM$ ;Just like a MOVEI except it puts the result in the left half ;of the AC. (SPEC[LEFT] makes a mask of -1,,0) .OPCODE[206] ;MOVSM MOVSM: ALU[AC] ACSEL[AC] DEST[AR] NORM $ D[AR] ROT[18.] DEST[MEMSTO] MEMST $ ;Swap halves and write it into memory like a MOVEM .OPCODE[207] ;MOVSS MOVSS: SLFFXM[MOVSS1] $ ;Finish read fetch of read-modify-write type cycle. ;Check to make sure effective address is writable. ;Jump if AC field in IR is non-zero D[MEM] ROT[18.] DEST[MEMSTO] MEMST $ ;Swap halves and write backing into same place in memory. ;*$*$*$ Move MOVSS1 here, a single instruction .OPCODE[210] ;MOVN MOVN: FIXM1 $ ACSEL[AC] D[MEM] ALU[0-D] DEST[AC MA] SPEC[CRYOV&MA_PC] JUMP[MAIN1] CYLEN[FIXM+1] $ ;Like MOVE except it negates the number it loads. ;Set flags. 400000,,0 will overflow. .OPCODE[211] ;MOVNI MOVNI: ACSEL[AC] D[IR] ALU[0-D] MASK[18.] DEST[AC MA] SPEC[CRYOV&MA_PC] JUMP[MAIN1] NORM $ ;Like MOVEI except that it load a negative number ;Set flags. Cannot overflow. .OPCODE[212] ;MOVNM MOVNM: ACSEL[AC] ALU[0-AC] DEST[MEMSTO] SPEC[CRYOV] MEMST $ ;Write negative of AC into memory. ;Set flags. 400000,,0 will overflow. .OPCODE[213] ;MOVNS MOVNS: SLFFXM[MOVNS1] $ ;Complete fetch of read-modify-write ;Jump if AC field (of IR) is non-zero, i.e. it loads an AC D[MEM] ALU[0-D] DEST[MEMSTO] SPEC[CRYOV] MEMST $ ;Write negative of number read back into memory. ; ; MOVM - Move Magnitude (Absolute value) ; .OPCODE[214] ;MOVM MOVM: FIXM1 $ ;Complete data fetch ACSEL[AC] D[MEM] DEST[AC] COND[OBUS<0] LBJUMP[MOVM1] C600 $ ;Load number. ;If negative, negate it to make it positive. ;In either case, start fetch of next instruction .USE[AREA214] ;$*$*$ Random hole .PAIR MOVM1: SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ ;Number is positive, leave it alone ;Start next instruction fetch ACSEL[AC] ALU[0-AC] DEST[AC MA] SPEC[CRYOV&MA_PC] JUMP[MAIN1] NORM$ ;Number is negative, make it positive. ;Start next instruction fetch .OPCODE[215] ;MOVMI MOVMI: ACSEL[AC] D[IR] MASK[18.] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;Immediate implies it's positive. Equivalent to MOVEI .OPCODE[216] ;MOVMM MOVMM: ACSEL[AC] ALU[AC] COND[OBUS<0] JUMP[MOVNM] CYLEN[C450] $ ;If AC is negative, store its negation and set flags ;Note: It will set overflow if AC contains 400000,,0 ACSEL[AC] ALU[AC] DEST[MEMSTO] SPEC[CRYOV] MEMST $ ;Otherwise, store positive form. (Both paths take same amount ;of time.) ;Also, set flags. .OPCODE[217] ;MOVMS MOVMS: COND[MA-AC] JUMP[MOVMS2] DEST[FIXMAC-MAPF-WRT] MAPF[NORM-WRT] CYLEN[FIXM]$ ;Finish fetch of read-modify-write ;Jump if we have to deal with two ACs COND[AC=0] LBJUMP[MOVMS1] NORM $ ;Split off case where we load AC as side effect .USE[AREA204] .PAIR MOVMS1: D[MEM] COND[OBUS<0] LBJUMP[MOVMS3] C550 $ ;AC field of IR is non-zero, AC is loaded as side effect D[MEM] COND[OBUS<0] LBJUMP[MOVMS4] C550 $ ;Reference is only to memory .PAIR MOVMS3: D[MEM] ACSEL[AC] SPEC[MA_PC] DEST[MA AC] JUMP[MAIN1] NORM $ ;Memory location is positive, just load AC D[MEM] ALU[0-D] ACSEL[AC] DEST[MEMSTO AC] SPEC[CRYOV] MEMST $ ;Load AC with negative of memory and write negative back ;into memory. ;Set flags. Will overflow if memory contains 400000,,0 .PAIR MOVMS4: SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ ;Memory is positive. Don't have to do anything here. D[MEM] ALU[0-D] DEST[MEMSTO] SPEC[CRYOV] JUMP[MSMAIN1] NORM $ ;Memory is negative. Store negation. ;Set flags. Will overflow if memory contains 400000,,0 ;Special cases for references to two ACs .PAIR MOVMS5: ACSEL[MA] ALU[0-AC] DEST[AC AR] SPEC[CRYOV] COND[AC=0] LBJUMP[MOVMS6] NORM $ ;'memory' AC is negative, negate it and put it somewhere ;the other AC loaded from. ;Then, decide whether to load it into another AC ACSEL[MA] ALU[AC] DEST[AR] COND[AC=0] LBJUMP[MOVMS6] NORM $ ;'memory' AC is positive. Put it somewhere the other AC ;can reference. ;Decide whether to load it into another AC .PAIR MOVMS6: ACSEL[AC] D[AR] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;AC field (of IR) is non-zero, load corresponding AC from ;saved value of 'memory' AC. ;Start next instruction fetch SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ ;AC field (of IR) is zero, just start next instruction fetch ; --- ;MA refers to an AC. Decide which special case we're dealing with. MOVMS2: ACSEL[MA] ALU[AC] COND[-OBUS<0] LBJUMP[MOVMS5] CYLEN[C500] $ ;Decide sign of 'memory' AC ;------------------------------------------------------------------------------ ; ; Integer Multiply ; ;------------------------------------------------------------------------------ .OPCODE[220] ;IMUL FIXM1 $ D[MEM] DEST[Q] JUMP[IMUL1] NORM $ .OPCODE[221] ;IMULI D[IR] MASK[18.] DEST[Q] JUMP[IMUL1] NORM $ .OPCODE[222] ;IMULM FIXM2 $ D[MEM] DEST[Q] JUMP[IMUL2] NORM $ .OPCODE[223] ;IMULB FIXM2 $ D[MEM] DEST[Q] JUMP[IMUL3] NORM $ .OPCODE[224] ;MUL FIXM1 $ D[MEM] DEST[Q] JUMP[MUL1] NORM $ .OPCODE[225] ;MULI D[IR] MASK[18.] DEST[Q] JUMP[MUL1] NORM $ .OPCODE[226] ;MULM FIXM2 $ D[MEM] DEST[Q] JUMP[MUL2] NORM $ .OPCODE[227] ;MULB FIXM2 $ D[MEM] DEST[Q] JUMP[MUL3] NORM $ ;*$*$* Move rest of multiply code here ;------------------------------------------------------------------------------ ; ; Integer Divide ; ;------------------------------------------------------------------------------ .OPCODE[230] ;IDIV FIXM1 $ IDIV9: ACSEL[AC] ALU[AC] DEST[Q AR] COND[-OBUS<0] LBJUMP[IDIV1] CYLEN[C500] $ ;LO PART TO Q, CHECK SIGN .OPCODE[231] ;IDIVI D[IR] MASK[18.] DEST[HOLD] JUMP[IDIV9] NORM $ ;IMMD .OPCODE[232] ;IDIVM FIXM2 $ ALU[AC] ACSEL[AC] DEST[Q AR] COND[-OBUS<0] LBJUMP[IDIV2] CYLEN[C500] $ ;LO PART TO Q, SAVE AC, CHECK SIGN .OPCODE[233] ;IDIVB FIXM2 $ ACSEL[AC] ALU[AC] DEST[Q AR] COND[-OBUS<0] LBJUMP[IDIV3] CYLEN[C500] $ .OPCODE[234] ;DIV FIXM1 $ DIV9: ACSEL[AC+1] ALU[AC] DEST[Q] JUMP[DIV1] $ ;LO PART .OPCODE[235] ;DIVI D[IR] MASK[18.] DEST[HOLD] JUMP[DIV9] $ ;IMMD .OPCODE[236] ;DIVM FIXM2 $ ALU[AC] ACSEL[AC+1] DEST[Q] JUMP[DIV2] $ .OPCODE[237] ;DIVB FIXM2 $ ALU[AC] ACSEL[AC+1] DEST[Q] JUMP[DIV3] $ ;$*$*$ Move rest of divide code here ;------------------------------------------------------------------------------ ; ; Shifts and Rotates ; ; Two branches are taken for each shift/rotate, depending on direction. ; The macro SH1ST handles that. The positive case gets ROTR loaded by ; that macro and other negative case will have to load it itself. ; ; Note that by the time we get here, indexing and indirection have ; already been done, so the left half of the IR contains an honest ; shift count, albeit not necessarily in the range -35..35 ; ;------------------------------------------------------------------------------ .DEFINE SH1ST [LAB1 LAB2] [ D[IR] COND[OBUS18] DEST[Q] JUMP[LAB1] C550 $ D[IR] MASK[10] DEST[Q ROTR] JUMP[LAB2] NORM $ ] .OPCODE[240] ;ASH SH1ST [ASHNEG ASHPLS] .OPCODE[241] ;ROT SH1ST [ROTNEG ROTPLS] .OPCODE[242] ;LSH SH1ST [LSHNEG LSHPLS] .OPCODE[243] ;JFFO (a funny kind of shift instruction) ACSEL[AC] ALU[AC] COND[OBUS=0] JUMP[JFFO1] DEST[AR] CYLEN[C450] $ ACSEL[AC+1] ALU[0] DEST[AC] JUMP[JFFO2] NORM $ .OPCODE[244] ;ASHC ACSEL[AC+1] D[MASK 43] ALU[D&AC] DEST[AR] NORM $ D[AR] ROT[1] DEST[Q] JUMP[ASHC1] NORM $ .OPCODE[245] ;ROTC ACSEL[AC+1] ALU[AC] DEST[Q] NORM $ D[IR] COND[-OBUS18] LBJUMP[ROTC1] C550 $ .OPCODE[246] ;LSHC ACSEL[AC+1] ALU[AC] DEST[Q] NORM $ D[IR] COND[-OBUS18] LBJUMP[LSHC1] C550 $ .OPCODE[247] ;(KAFIX at SAIL: "A. Kotok should have done this") ACSEL[AC] ALU[AC] DEST[HOLD AR] COND[-OBUS<0] JUMP[KAFIXP] C550 $ ;Load up things for FIXER, check for positive mantissa ACSEL[AC] ALU[0-AC] DEST[AR] JUMP[KAFIXN] NORM $ ;Negate AR so that its exponent can be used. ;------------------------------------------------------------------------------ ; Exchange AC and memory ;------------------------------------------------------------------------------ .OPCODE[250] ;EXCH FIXM2 $ ;Finish fetch of read-modify-write, checking for faults ACSEL[AC] D[MEM] DEST[MEMSTO O_AC] MEMST $ ;Store result of fetch into AC, writing the old contents of ;that AC into memory (O_AC means store new AC and output old ;contents). ;------------------------------------------------------------------------------ ; Block Transfer Instruction ;------------------------------------------------------------------------------ .OPCODE[251] ;BLT D[MASK 16] ROT[4] ACSEL[AC] ALU[D&AC] COND[OBUS=0] JUMP[BLTA1] C550 $ ;J IF DEST IS AC D[MASK 16] ROT[26] ACSEL[AC] ALU[D&AC] COND[-OBUS=0] LBJUMP[BLTA2] C600 $ ; J ON SRC NOT AC ;------------------------------------------------------------------------------ ; Conditional jumps which add one to both halves ; ; Caution: With these instructions, overflow from the right half will be ; added to the left half, as on a KA. ;------------------------------------------------------------------------------ .OPCODE[252] ;AOBJP D[CONST 1,,1] ACSEL[AC] ALU[D+AC] DEST[AC] COND[OBUS<0] JUMP[MAIN] C600 $ ;Add to both halves. If result is negative, do not jump DOJUMP $ .OPCODE[253] ;AOBJN D[CONST 1,,1] ACSEL[AC] ALU[D+AC] DEST[AC] COND[-OBUS<0] JUMP[MAIN] C600 $ DOJUMP $ ;------------------------------------------------------------------------------ ; Jump Instructions (and halts) ; ; Caution: Halts set PC to effective address instead of the instruction ; that caused the halt. This is especially bad because most ; programs which do not use UUOs place a halt in location 40, ; and the location of the UUO is then lost on an F2. This ; might be cured by replicating the instruction fetch seqeunce ; herein with the copying of the IR into the PC happening later ; during that sequence. ;------------------------------------------------------------------------------ .OPCODE[254] ;JRST D[IR] DEST[MA PC] COND[AC=0] JUMP[MAIN1] NORM $ ;Make ordinary jumps as fast as possible. Always load the PC ;from the effective address, even on halts!?! D[IR] ROT[12] MASK[1] COND[OBUS=0] LBJUMP[JRST1] C550 $ ;Seperate according to the 10 bit of the AC field. .OPCODE[255] ;JFCL D[IR] ROT[15] MASK[4] DEST[AR] COND[AC=0] JUMP[MAIN] NORM $ ;Check AC field and jump to instruction fetch if zero. ;JFCL 0, is the fastest no-op on a KA D[PC] DEST[Q] JUMP[JFCL1] NORM $ .OPCODE[256] ;XCT FIXM1 COND[-AC=0] JUMP[XCT1] $ D[PC] ALU[D-1] DEST[PC] JUMP[XCT2] NORM $ .OPCODE[257] ;A No-Op on KA's not having special features JUMP[MAIN] NORM $ ;------------------------------------------------------------------------------ ; ; Stack Instructions ; ; Caution: If a stack crosses zero (i.e. a carry from the right half ; occurs, the left half will be off by one, as on a KA ; (People who wrap their stacks around and thru ACs deserve to ; lose!) ;------------------------------------------------------------------------------ .OPCODE[260] ;PUSHJ ACSEL[AC] D[CONST 1,,1] ALU[D+AC] DEST[AC MA] COND[CRY0] JUMP[PDLO1] C600 $ ;Increment stack pointer. ;Jump on overflow (overflow code will complete instruction) D[PC] DEST[MEMSTO] JUMP[PUSHJ1] NORM $ ;Store the PC and flags on the stack .OPCODE[261] ;PUSH FIXM1 $ ;Complete fetch of thing to push D[MEM] DEST[AR] JUMP[PUSH1] NORM $ ;Move it somewhere else so we set MA to point to stack. ;(Setting the MA implies a read, which would destroy the thing ;to push). ;*$*$* Go elsewhere to finish instruction .OPCODE[262] ;POP ACSEL[AC] D[CONST 1,,1] ALU[AC-D] DEST[MA O_AC] COND[-CRY0] JUMP[PDLO3] C600 $ ;Decrement stack pointer, but setting the MA to the old top of ;stack. ;If stack underflow, jump. (Underflow code will finish the ;instruction). MAPF[PPOP] ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] JUMP[POP1] CYLEN[FIXM] $ ;If page fault, trap to special code to handle POP ;*$*$* Go elsewhere to finish instruction .OPCODE[263] ;POPJ ACSEL[AC] D[CONST 1,,1] ALU[AC-D] DEST[MA O_AC] COND[-CRY0] JUMP[PDLO4] C600 $ ;Decrement stack pointer, but setting the MA to the old top of ;stack. ;If stack underflow, jump. (Underflow code will finish the ;instruction). MAPF[PPOP] ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] JUMP[POPJ1] CYLEN[FIXM] $ ;If page fault, trap to special code to handle POP ;*$*$* Go elsewhere to finish instruction .OPCODE[264] ;JSR D[PC] DEST[AR MEMSTO] COND[MA-AC] JUMP[JSR2] NORM $ ;Write PC (and flags) into effective address. ;Watch for special case of store into AC MAPF[STO] D[MA] ALU[D+1] DEST[PC] SPEC[CLR-HALF] JUMP[MAIN] CYLEN[MEMSTO] $ ;Set PC into one after effective address (where we stored old ;PC) and take next instruction from there. ;Make sure some nurd hasn't left the BIS flag on. (*** i assume ; that's what going on here. TVR-Apr80) .OPCODE[265] ;JSP D[PC] ACSEL[AC] DEST[AC] NORM $ ;Store PC (and flags) in AC JSP1: D[MA] DEST[PC] JUMP[MAIN1] SPEC[CLR-HALF] NORM $ ;Jump to effective address ;Make sure some nurd hasn't left the BIS flag on. (*** i assume ; that's what going on here. TVR-Apr80) .OPCODE[266] ;JSA D[PC] MASK[18.] DEST[O_AC AR] ACSEL[AC] NORM $ ;Copy PC into left half of AC and save old contents of AC in AR ; DID SAVE A CYCLE WITH O_AC **** D[MA] ROT[18.] SPEC[LEFT] ALU[DORAC] ACSEL[AC] DEST[AC] JUMP[JSA1] NORM $ ;Put effective address into right half, i.e. were the old ;contents of the AC is stored. ;(This is the FORTRAN subroutine call, in case you were ; wondering why it was so wierd...) ;*$*$* (Finish instruction elsewhere) .OPCODE[267] ;JRA ACSEL[AC] ALU[AC] DEST[AR] NORM $ ;Save the return address in AR D[AR] ROT[18.] MASK[18.] DEST[MA] JUMP[JRA1] NORM $ ;Begin read of location containing what's to be restored into ;the AC (to invert a JSA) ;*$*$* (Finish instruction elsewhere) ;------------------------------------------------------------------------------ ; ; Integer Add and Subtract ; ;------------------------------------------------------------------------------ ;These two macros make xxx,xxxI,xxxM,xxxB for instructions which map into a ;single 2901 instruction involving AC and MEM. OP is thing to put in the ;ALU field to do this 2901 instruction. ; ;ADOP and LOGOP differ only in that ADOP sets flags, and can get integer ;overflow ; .DEFINE ADOP [OP] BEGIN ADOP FIXM1 $ ACSEL[AC] D[MEM] ALU[ OP ] DEST[AC MA] SPEC[CRYOV&MA_PC] JUMP[MAIN1] CYLEN[FIXM+1] $ ACSEL[AC] D[IR] MASK[18.] ALU[ OP ] DEST[AC MA] SPEC[CRYOV&MA_PC] JUMP[MAIN1] NORM $ NOP $ FIXM2 $ ACSEL[AC] D[MEM] ALU[ OP ] DEST[MEMSTO] SPEC[CRYOV] MEMST $ FIXM2 $ ACSEL[AC] D[MEM] ALU[ OP ] DEST[MEMSTO AC] SPEC[CRYOV] MEMST $ END ADOP .DEFINE LOGOP [OP] BEGIN LOGOP FIXM1 $ ACSEL[AC] D[MEM] ALU[ OP ] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] CYLEN[FIXM+1] $ ACSEL[AC] D[IR] MASK[18.] ALU[ OP ] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ NOP $ FIXM2 $ ACSEL[AC] D[MEM] ALU[ OP ] DEST[MEMSTO] MEMST $ FIXM2 $ ACSEL[AC] D[MEM] ALU[ OP ] DEST[MEMSTO AC] MEMST $ END LOGOP .OPCODE[270] ;Opcodes 270-273: ADD,ADDI,ADDM,ADDB ADOP[D+AC] ;Macro defines four instructions. See above .OPCODE[274] ;Opcodes 274-277: SUB,SUBI,SUBM,SUBB ADOP[AC-D] ;Macro defines four instructions. See above ;------------------------------------------------------------------------------ ; ; Conditional Instructions ; ; Instruction dispatch sends each group of eight instructions to one ; place. The condition JCOND looks at the IR to decide whether the ; condition specified by the low order three bits of the opcode has ; been satisfied. ; ;------------------------------------------------------------------------------ ;Compare AC to effective address .OPCODE[300] ;CAI D[IR] MASK[18.] ACSEL[AC] ALU[AC-D] COND[-JCOND] JUMP[MAIN] C600 $ DOSKIP $ AREA260: ;Recover space from hole in instruction dispatch ;Compare AC to memory .OPCODE[310] ;CAM FIXM1 $ D[MEM] ACSEL[AC] ALU[AC-D] COND[-JCOND] JUMP[MAIN] C600 $ DOSKP1: DOSKIP $ AREA262: ;Recover space from hole in instruction dispatch ;Jump on AC [compared with zero] .OPCODE[320] ;JUMP D[CONST 0] ACSEL[AC] ALU[AC+D] COND[-JCOND] JUMP[MAIN] C600 $ DOJUMP $ AREA264: ;Recover space from hole in instruction dispatch ;Skip on memory [compared with zero] .OPCODE[330] ;SKIP FIXM1 COND[AC=0] JUMP[SKIPX1] $ ;Jump if AC not loaded as side effect D[MEM] ALU[D-0] ACSEL[AC] DEST[AC] COND[-JCOND] JUMP[MAIN] C600 $ ;AC field (in IR) is zero. Just skip on appropriate condition DOSKIP $ SKIPX1: D[MEM] ALU[D-0] COND[-JCOND] JUMP[MAIN] C600 $ ;Load memory into AC as well as skipping on appropriate ;condition DOSKIP $ AREA266: ;Recover space from hole in instruction dispatch ;Add One to AC and jump [on AC compared with zero] .OPCODE[340] ;AOJ ACSEL[AC] ALU[AC+1] DEST[AC] SPEC[CRYOV] COND[-JCOND] JUMP[MAIN] C600 $ DOJUMP $ AREA270: ;Recover space from hole in instruction dispatch ;Add One to Memory and skip [on memory compared to zero] .OPCODE[350] ;AOS FIXM2 COND[AC=0] JUMP[ASOS1] $ ;Finish fetch part of read-modify-write ;Jump if AC is not loaded as a side effect. D[MEM] ALU[D+1] ACSEL[AC] DEST[AC MEMSTO] SPEC[CRYOV] COND[JCOND] LBJUMP[ASOS2] C600 $ ;(AC field (in IR) is non-zero. Load AC as side effect.) ;Increment memory and store result in AC. ;Set flags (set overflow if memory was 377777,,777777) ;Decide where or not to skip before checking for store to AC .PAIR ASOS2: MEMST $ ;Do not skip. Finish store (checking for store to AC) D[PC] ALU[D+1] DEST[PC] MEMST $ ;Do skip. Finish store. ; --- ASOS1: D[MEM] ALU[D+1] DEST[MEMSTO] SPEC[CRYOV] COND[JCOND] LBJUMP[ASOS2] C600 $ ;Simply increment memory location. Otherwise, same as above. AREA272 = . ;Recover space from hole in instruction dispatch ;Subtract One from AC and jump [on AC compared with zero] .OPCODE[360] ;SOJ ACSEL[AC] ALU[AC-1] DEST[AC] SPEC[CRYOV] COND[-JCOND] JUMP[MAIN] C600 $ DOJUMP $ AREA274: ;Recover space from hole in instruction dispatch ;Subtract One from Memory and skip [on memory compared to zero] .OPCODE[370] ;SOS FIXM2 COND[AC=0] JUMP[ASOS3] $ ;Finish fetch part of read-modify-write ;Jump if AC is not loaded as a side effect. D[MEM] ALU[D-1] ACSEL[AC] DEST[AC MEMSTO] SPEC[CRYOV] COND[JCOND] LBJUMP[ASOS2] C600 $ ;(AC field (in IR) is non-zero. Load AC as side effect.) ;Decrement memory and store result in AC. ;Set flags (set overflow if memory was 400000,,0) ;Decide where or not to skip before checking for store to AC ASOS3: D[MEM] ALU[D-1] DEST[MEMSTO] SPEC[CRYOV] COND[JCOND] LBJUMP[ASOS2] C600 $ ;Simply decrement memory location. Otherwise, same as above. AREA276 = . ;Recover space from hole in instruction dispatch ;------------------------------------------------------------------------------ ; ; Boolean Instructions ; ;------------------------------------------------------------------------------ .DEFINE CLRAC [] [ ALU[0] ACSEL[AC] DEST[AC] NORM ] .OPCODE[400] ;SETZ CLRAC JUMP[MAIN] $ .OPCODE[401] ;SETZI CLRAC JUMP[MAIN] $ .OPCODE[402] ;SETZM ALU[0] DEST[MEMSTO] MEMST $ .OPCODE[403] ;SETZB ALU[0] DEST[MEMSTO AC] MEMST $ .OPCODE[404] ;AND,ANDI,ANDM,ANDB ;Generates code for four instructions. See ADD (ADOP) LOGOP[D&AC] .OPCODE[410] ;ANDCA FIXM1 $ ACSEL[AC] ALU[NOTAC] DEST[Q] JUMP[ANDCA1] CYLEN[FIXM+1] $ .OPCODE[411] ;ANDCAI ALU[NOTAC] DEST[Q] ACSEL[AC] NORM $ D[IR] MASK[18.] ACSEL[AC] ALU[D&Q] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ .OPCODE[412] ;ANDCAM FIXM2 $ ACSEL[AC] ALU[NOTAC] DEST[Q] JUMP[ANDCA2] CYLEN[FIXM+1] $ .OPCODE[413] ;ANDCAB FIXM2 $ ACSEL[AC] ALU[NOTAC] DEST[Q] JUMP[ANDCA3] CYLEN[FIXM+1] $ .OPCODE[414] ;SETM,SETMI,SETMM,SETMB SETM: LOGOP[ D ] .OPCODE[420] ;ANDCM,ANDCMI,ANDCMM,ANDCMB LOGOP[-D&AC] .OPCODE[424] ;SETA,SETAI,SETAM,SETAB LOGOP[ AC ] $ .OPCODE[430] ;XOR,XORI,XORM,XORB LOGOP[AC#D] .OPCODE[434] ;IOR,IORI,IORM,IORB LOGOP[DORAC] .OPCODE[440] ;ANDCB FIXM1 $ ACSEL[AC] ALU[DORAC] DEST[Q] D[MEM] JUMP[ACBI1] CYLEN[FIXM+1] $ .OPCODE[441] ;ANDCBI ACSEL[AC] D[IR] MASK[18.] ALU[DORAC] DEST[Q] NORM $ ACBI1: ACSEL[AC] ALU[NOTQ] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ .OPCODE[442] ;ANDCBM FIXM2 $ ACSEL[AC] ALU[DORAC] D[MEM] DEST[Q] JUMP[LOG2] CYLEN[FIXM+1] $ .OPCODE[443] ;ANDCBB FIXM2 $ ACSEL[AC] ALU[DORAC] D[MEM] DEST[Q] JUMP[LOG3] CYLEN[FIXM+1] $ .OPCODE[444] ;EQV,EQVI,EQVM,EQVB LOGOP[AC/#D] .OPCODE[450] ;SETCA,SETCAI,SETCAM,SETCAB LOGOP[NOTAC] .OPCODE[454] ;ORCA FIXM1 $ ACSEL[AC] D[MEM] ALU[-D&AC] DEST[Q] JUMP[OCAI1] CYLEN[FIXM+1] $ .OPCODE[455] ;ORCAI ACSEL[AC] D[IR] MASK[18.] ALU[-D&AC] DEST[Q] NORM $ OCAI1: ACSEL[AC] ALU[NOTQ] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ .OPCODE[456] ;ORCAM FIXM2 $ ACSEL[AC] ALU[-D&AC] D[MEM] DEST[Q] JUMP[LOG2] CYLEN[FIXM+1] $ .OPCODE[457] ;ORCAB FIXM2 $ ACSEL[AC] ALU[-D&AC] D[MEM] DEST[Q] JUMP[LOG3] CYLEN[FIXM+1] $ .OPCODE[460] ;SETCM,SETCMI,SETCMM,SETCMB LOGOP[NOTD] .OPCODE[464] ;ORCM,ORCMI,ORCMM,ORCMB FIXM1 $ D[MEM] ALU[NOTD] DEST[Q] JUMP[OCMI1] CYLEN[FIXM+1] $ .OPCODE[465] ;ORCMI D[IR] MASK[18.] ALU[NOTD] DEST[Q] NORM $ OCMI1: ACSEL[AC] ALU[QORAC] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ .OPCODE[466] ;ORCMM FIXM2 $ D[MEM] ALU[NOTD] DEST[Q] JUMP[ORCM2] CYLEN[FIXM+1] $ .OPCODE[467] ;ORCMB FIXM2 $ D[MEM] ALU[NOTD] DEST[Q] JUMP[ORCM3] CYLEN[FIXM+1] $ .OPCODE[470] ;ORCB FIXM1 $ ACSEL[AC] D[MEM] ALU[D&AC] DEST[Q] JUMP[OCBI1] CYLEN[FIXM+1] $ .OPCODE[471] ;ORCBI ACSEL[AC] D[IR] MASK[18.] ALU[D&AC] DEST[Q] NORM $ OCBI1: ACSEL[AC] ALU[NOTQ] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ .OPCODE[472] ;ORCBM FIXM2 $ ACSEL[AC] ALU[D&AC] D[MEM] DEST[Q] JUMP[LOG2] CYLEN[FIXM+1] $ .OPCODE[473] ;ORCBB FIXM2 $ ACSEL[AC] ALU[D&AC] D[MEM] DEST[Q] JUMP[LOG3] CYLEN[FIXM+1] $ .OPCODE[474] ;SETO ACSEL[AC] ALU[-1] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ .OPCODE[475] ;SETOI ACSEL[AC] ALU[-1] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ .OPCODE[476] ;SETOM ALU[-1] DEST[MEMSTO] MEMST $ .OPCODE[477] ;SETOB ALU[-1] ACSEL[AC] DEST[MEMSTO AC] MEMST $ NOP $ ;------------------------------------------------------------------------------ ; ; Half Word Instructions ; ;------------------------------------------------------------------------------ .DEFINE MH1 [ RR MM SS RR2 D1 OP1 JJ CYL1 D2 SS1 ] [ FIXM1 $ D[MEM] ROT[ RR ] MASK[ MM ] SPEC[ SS ] ACSEL[AC] DEST[AC MA] JUMP[MAIN1] CYLEN[FIXM+1] $ D[MA] ROT[RR] MASK[ MM ] SPEC[ SS ] ACSEL[AC] DEST[AC MA] JUMP[MAIN1] NORM $ NOP $ D[MASK 22] ROT[ RR2 ] ACSEL[AC] ALU[D&AC] DEST[ D1 ] COND[-MA-AC] OP1 [ JJ ] CYLEN[ CYL1 ] $ D[AR] ROT[18.] DEST[MEMSTO] MEMST $ ACSEL[MA] ALU[AC] COND[MA-AC] JUMP[ D2 ] DEST[FIXMAC-MAPF-WRT] MAPF[3] CYLEN[FIXM] $ D[MEM] ROT[ RR ] MASK[ MM ] SPEC[ SS1 ] DEST[MEMSTO] COND[-AC=0] LBJUMP[HSMN1] CYLEN[FIXM+1] $ ] .DEFINE MH2 [ RR MM SS CC OP DST RR2 DST2 CC2 OP2 JJ CYL2 RR3 DST3 CC4 ] [ FIXM1 $ D[MEM] ROT[ RR ] MASK[ MM ] SPEC[ SS ] ACSEL[AC] DEST[AC AR] COND[ CC ] OP [ DST ] CYLEN[FIXM+1] $ D[MA] ROT[ RR ] MASK[ MM ] SPEC[ SS ] ACSEL[AC] DEST[AC AR] COND[ CC ] OP [ DST ] NORM $ NOP $ D[MASK 22] ROT[ RR2 ] ACSEL[AC] ALU[DORAC] DEST[Q DST2 ] COND[ CC2 ] OP2[JJ] CYLEN[ CYL2 ] $ D[AR] ROT[RR3] DEST[MEMSTO] MEMST $ FIXM2 $ D[MEM] ROT[ RR ] DEST[Q AR] COND[ CC4 ] LBJUMP[ DST3] CYLEN[FIXM+1] $ ] .DEFINE MH3 [ RR MM SS JDST RR2 JDST2 DST OP1 JJ ] [ FIXM1 $ D[MEM] ROT[ RR ] MASK[ MM ] SPEC[ SS ] ACSEL[AC] DEST[O_AC AR] JUMP[ JDST ] CYLEN[FIXM+1] $ D[MA] ROT[ RR ] MASK[ MM ] SPEC[ SS ] ACSEL[AC] DEST[O_AC AR] JUMP[ JDST ] NORM $ NOP $ FIXM2 $ D[MASK 22] ROT[ RR2 ] ACSEL[AC] ALU[D&AC] DEST[Q AR] JUMP[ JDST2 ] CYLEN[FIXM+1] $ ACSEL[MA] ALU[AC] DEST[ DST ] MAPF[3] COND[-AC=0] OP1[JJ] CYLEN[FIXM] $ D[MEM] ROT[ RR ] MASK[ MM ] SPEC[ SS ] DEST[Q AR] COND[-AC=0] LBJUMP[HHS] CYLEN[FIXM+1] $ ] .OPCODE[500] ;HLL,HLLI,HLLM,HLLS MH3[ 0 0 LEFT HRAR 22 HLLM1 0 LBJUMP HMV ] ;HRL MH3[ 22 0 LEFT HRAR 0 HRLM1 FIXMAC-MAPF-WRT CONTA 0] ;HLLZ MH1[0 0 LEFT&MA_PC 22 MEMSTO LBJUMP MSMAIN NORM HLLZS1 LEFT] ;HRLZ MH1[22 0 LEFT&MA_PC 0 AR CONTA 0 NORM HRLZS1 LEFT] ;HLLO MH2[0 44 0 0 JUMP HOR 0 MEMSTO -MA-AC LBJUMP MSMAIN NORM 0 HLLOS1 -AC=0] ;HRLO MH2[22 44 0 0 JUMP HOR 22 AR 0 CONTA 0 NORM 22 HLLOS1 -AC=0] ;HLLE MH2[0 0 LEFT OBUS<0 LBJUMP HLSZ 0 AR -OBUS<0 JUMP HLLEM1 C550 0 HLLES1 OBUS<0 ] ;HRLE MH2[22 0 LEFT OBUS<0 LBJUMP HLSZ 22 AR -OBUS18 JUMP HRLEM1 C550 22 HLLES1 OBUS<0 ] ;HRR MH3[0 22 0 HLAR 0 HRRM1 0 LBJUMP HMV ] ;HLR MH3[22 22 0 HLAR 22 HLRM1 FIXMAC-MAPF-WRT CONTA 0] ;HRRZ MH1[0 22 MA_PC 0 MEMSTO LBJUMP MSMAIN NORM HRRZS1 0] ;HLRZ MH1[22 22 MA_PC 22 AR CONTA 0 NORM HLRZS1 0] ;HRRO MH2[0 44 0 0 JUMP HOL 22 MEMSTO -MA-AC LBJUMP MSMAIN NORM 0 HRROS1 -AC=0] ;HLRO MH2[22 44 0 0 JUMP HOL 0 AR 0 CONTA 0 NORM 22 HRROS1 -AC=0] ;HRRE MH2[0 22 0 OBUS18 LBJUMP HRSZ 22 AR -OBUS18 JUMP HRREM1 C550 0 HRRES1 OBUS18] ;HLRE MH2[22 22 0 OBUS18 LBJUMP HRSZ 0 AR -OBUS<0 JUMP HLREM1 C550 22 HRRES1 OBUS18] ;------------------------------------------------------------------------------ ; ; Bit Test Instructions ; ; Caution: Instruction dispatch for these instructions is peculiar. ; ;------------------------------------------------------------------------------ .OPCODE[600] ;TRN GROUP D[IR] MASK[18.] ACSEL[AC] ALU[D&AC] SPEC[MA_PC] DEST[MA] COND[-JCOND] JUMP[MAIN1] C550 $ DOSKIP $ .OPCODE[601] ;TLN GROUP D[IR] ROT[18.] ACSEL[AC] ALU[D&AC] SPEC[LEFT&MA_PC] DEST[MA] COND[-JCOND] JUMP[MAIN1] C550 $ DOSKIP $ .DEFINE T2GRP [OP RR MM SS] [ ACSEL[AC] D[IR] ROT[RR] MASK[MM] SPEC[SS] ALU[OP] DEST[AC] NORM $ DOSKIP $ ] ;Following code is NOT dispatched to, it is JUMPed to. TRZ1: T2GRP [-D&AC 0 22 0 ] TLZ1: T2GRP [-D&AC 22 0 LEFT] TRO1: T2GRP [DORAC 0 22 0] TLO1: T2GRP [DORAC 22 0 LEFT] TRC1: T2GRP [D#AC 0 22 0] TLC1: T2GRP [D#AC 22 0 LEFT] ;(No space left before dispatch entry) .OPCODE[610] ;TDN GROUP FIXM1 $ D[MEM] ACSEL[AC] ALU[D&AC] COND[JCOND] LBJUMP[SKMAIN] C600 $ .OPCODE[611] ;TSN GROUP FIXM1 $ D[MEM] ACSEL[AC] ROT[18.] ALU[D&AC] COND[JCOND] LBJUMP[SKMAIN] C600 $ ;(Following is not dispatched to. It probably belongs with MSMAIN, etc.) .PAIR SKMAIN: SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ DOSKIP $ AREA342: ;Recover space from hole in instruction dispatch .DEFINE T1GRP [OP RR MM SS1 SS2 D1] [ ACSEL[AC] D[IR] ROT[RR] MASK[MM] SPEC[SS1] ALU[D&AC] COND[JCOND] JUMP[D1] C550 $ ACSEL[AC] D[IR] ROT[RR] MASK[MM] SPEC[SS2] ALU[OP] DEST[AC MA] JUMP[MAIN1] NORM $ ] .OPCODE[620] ;TRZ GROUP T1GRP [-D&AC 0 22 0 MA_PC TRZ1] .OPCODE[621] ;TLZ GROUP T1GRP [-D&AC 22 0 LEFT LEFT&MA_PC TLZ1] AREA344: ;Recover space from hole in instruction dispatch .OPCODE[630] ;TDZ FIXM1 $ ALU[AC] ACSEL[AC] DEST[Q] JUMP[TDZ1] NORM $ .OPCODE[631] ;TSZ FIXM1 $ ALU[AC] ACSEL[AC] DEST[Q] NORM $ ; \ / ;Following is not in instruction dispatch ACSEL[AC] D[MEM] ROT[18.] ALU[-D&AC] DEST[AC] SHORT $ TSZ2: D[MEM] ROT[18.] ALU[D&Q] COND[JCOND] LBJUMP[SKMAIN] C600 $ TDZ1: ACSEL[AC] D[MEM] ALU[-D&AC] DEST[AC] SHORT $ TDZ2: D[MEM] ALU[D&Q] COND[JCOND] LBJUMP[SKMAIN] C600 $ AREA346: ;Recover space from hole in instruction dispatch .OPCODE[640] ;TRC GROUP T1GRP [D#AC 0 22 0 MA_PC TRC1] .OPCODE[641] ;TLC GROUP T1GRP [D#AC 22 0 LEFT LEFT&MA_PC TLC1] AREA350: ;Recover space from hole in instruction dispatch .OPCODE[650] ;TDC FIXM1 $ ALU[AC] ACSEL[AC] DEST[Q] JUMP[TDC1] NORM $ .OPCODE[651] ;TSC FIXM1 $ ALU[AC] ACSEL[AC] DEST[Q] NORM $ ACSEL[AC] D[MEM] ROT[18.] ALU[AC#D] DEST[AC] JUMP[TSZ2] NORM $ TDC1: ACSEL[AC] D[MEM] ALU[AC#D] DEST[AC] JUMP[TDZ2] NORM $ AREA352: ;Recover space from hole in instruction dispatch .OPCODE[660] ;TRO GROUP T1GRP [DORAC 0 22 0 MA_PC TRO1] .OPCODE[661] ;TLO GROUP T1GRP [DORAC 22 0 LEFT LEFT&MA_PC TLO1] AREA354: ;Recover space from hole in instruction dispatch .OPCODE[670] ;TDO GROUP FIXM1 $ ALU[AC] ACSEL[AC] DEST[Q] JUMP[TDO1] NORM $ .OPCODE[671] ;TSO GROUP FIXM1 $ ALU[AC] ACSEL[AC] DEST[Q] NORM $ ACSEL[AC] D[MEM] ROT[18.] ALU[DORAC] DEST[AC] JUMP[TSZ2] NORM $ TDO1: ACSEL[AC] D[MEM] ALU[DORAC] DEST[AC] JUMP[TDZ2] NORM $ AREA356: ;Recover space from hole in instruction dispatch ; IOT GROUP -- FOR NOW ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; ;;;; CAUTION: Hardware currently does not check for User when doing ;;;; ;;;; IOTs. Most, but not all, now check it in micro code. The ;;;; ;;;; instruction dispatch hardware is probably the right place to ;;;; ;;;; check for this, but try to convince Poole of that... ;;;; ;;;; ;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .repeat 0[ .DEFINE IOTDIS [ WHERE ] [ D[IR] ROT[15] MASK[4] DEST[Q] NORM $ D[IR] ROT[15] MASK[4] ALU[D+Q] DEST[Q] SHORT $ D[CONST WHERE] ROT[6] ALU[DORQ] SDISP CYLEN[C500] $ ] ];repeat 0 .DEFINE IOTDIS [ WHERE ] [ D[IR] ROT[16] MASK[5] DEST[Q] NORM $ D[CONST WHERE] ROT[6] ALU[DORQ] SDISP CYLEN[C500] $ ];.DEFINE IOTDIS ;Bit 14 is guaranteed zero by instruction decode process and therefore ;doubling can be obtained by extraction. TVR-Apr80 .OPCODE[700] ;APR & PI MAPF[2] D[CONST 6] DEST[DEV-ADR] COND[-USER] LBJUMP[APIOT] NORM $ NOP $ .OPCODE[701] ILGIOT $ NOP $ .OPCODE[702] ;UNUSED & MAP MAPF[2] D[CONST 1] DEST[DEV-ADR] NORM $ D[IR] ROT[15] MASK[4] DEST[Q] COND[-USER] LBJUMP[MAPIOT] NORM $ .REPEAT 7 [ILGIOT $ NOP $ ] .OPCODE[712] ;CTY & LPT MAPF[2] D[CONST 4] DEST[DEV-ADR] NORM COND[-USER] LBJUMP[CTYIOT] $ NOP $ ILGIOT $ NOP $ ILGIOT $ NOP $ ;DISK CTRL IOTS-- 140 - 174 .OPCODE[715] ;DISK CTRL IOTS-- OPCODES 715 TO 724 D[CONST 10] DEST[DEV-ADR] SPEC[IOB-IN] COND[USER] JUMP[UDSKST] $ MAPF[0] D[IOD] DEST[MEMSTO] COND[-MA-AC] LBJUMP[SMAIN] $ D[CONST 10] DEST[DEV-ADR] SPEC[IOB-IN] COND[USER] JUMP[UDSKST] $ MAPF[1] D[IOD] DEST[MEMSTO] COND[-MA-AC] LBJUMP[SMAIN] $ D[CONST 10] DEST[DEV-ADR] SPEC[IOB-IN] COND[USER] JUMP[UDSKST] $ MAPF[2] D[IOD] DEST[MEMSTO] COND[-MA-AC] LBJUMP[SMAIN] $ D[CONST 10] DEST[DEV-ADR] SPEC[IOB-IN] COND[USER] JUMP[UDSKST] $ MAPF[3] D[IOD] DEST[MEMSTO] COND[-MA-AC] LBJUMP[SMAIN] $ FIXML PUSHJ[SET-DSK-OUT] $ ;ld cmd -- opcode 721 MAPF[4] d[ar] DEST[2] DEST-A-MEM JUMP[MAIN] $ FIXML PUSHJ[SET-DSK-OUT] $ MAPF[5] DEST[MA] SPEC[MA_PC] JUMP[MAIN1] $ FIXML PUSHJ[SET-DSK-OUT] $ MAPF[6] DEST[MA] SPEC[MA_PC] JUMP[MAIN1] $ FIXML PUSHJ[SET-DSK-OUT] $ MAPF[7] DEST[MA] SPEC[MA_PC] JUMP[MAIN1] $ ;TAPE IOTS - OPCODES 725 - 732 --Dispatch entries on page headed ";TAPE DISP" .OPCODE[733] .REPEAT 4 [ILGIOT $ ;SKIP OPCODES 733 - 736 NOP $ ] .OPCODE[737] ;DLS iot's (DLS is device 370) .REPEAT 1 - DLS [ ;If DLS present, this entry is part of DLS code. D[IR] ROT[12.] C550 COND[OBUS<0] JUMP[MAIN] $ ;If it can't be a CONSZ, do nothing. D[PC] ALU[D+1] DEST[PC] NORM JUMP[MAIN] $ ;If it could be a CONSZ, assume it is and perform a skip. ] ;1 - DLS ;skip space for disk cono,coni, etc. OPS 740 - 743 ;locs 3700 to 3707 ; these dispatch entries are on dsk page. .OPCODE[744] ;Tymnet opcodes (or undefined) .repeat 1 - TYMNET - DR11P [ .repeat 4 [ ilgiot $ nop $ ;if no tymnet, 744-747 = nop ] ] .repeat tymnet [ ;skip space for TYMNET IOTS. OPS 744 - 747 ; these dispatch entries are on TYMNET page. ] .OPCODE[750] ;READ ECC INFO D[11] A-MEM-APR DEST[MEMSTO] MEMST $ ;Get info on last ECC error from A-MEM(1), store in eff. adr. NOP $ .OPCODE[751] ;Undefined ILGIOT $ NOP $ .OPCODE[752] ; .REPEAT 1 - VC [ ILGIOT $ NOP $ ];.REPEAT 1 - VC .REPEAT VC [ ;Versatec D[CONST VCDEV] DEST[DEV-ADR] NORM COND[-USER] LBJUMP[VCIOT] $ ;Set micro device address for Versatec and check for ;IOT-User mode NOP $ ];.REPEAT VC .OPCODE[753] ;Undefined ILGIOT $ NOP $ .OPCODE[754] ;Undefined ILGIOT $ NOP $ .OPCODE[755] ;IMP (BBN), device code 550 .REPEAT 1 - IMP [ILGIOT $ NOP $ ];1 - IMP .REPEAT IMP [ ;Reserve space for the IMP IOT dispatch instructions IMP-IOT: ];IMP .OPCODE[756] ;Undefined .REPEAT (757 - 756 + 1) [ILGIOT $ NOP $ ] TIMER-IOTS: .OPCODE[760] ;760:765 .REPEAT 0 * (1 - TIMER) * (765 - 760 + 1) [ILGIOT $ NOP $ ] ;;; : TIMER-IOTS + 12. ;LEAVE SPACE FOR OPCODES 760-765 ;*** This is an unreasonably large waste of opcode space. It should dispatch ;*** on the AC field at least if normal PDP-10 I/O opcodes aren't suitable. ;*** Furthermore, this kind of opcode has no chance of being properly ;*** disassembled by DDT. TVR-Apr80 .OPCODE[774] .REPEAT STANSW [ ;OP 774 D[CONST GRN-UDEV] DEST[DEV-ADR] NORM COND[-USER] LBJUMP[GRNIOT] $ ;Set micro device address for Grinnell and check for ;IOT-User mode NOP $ ] .REPEAT 1 - STANSW [CURRENTLY-UNUSED[1] JUMP[MAIN] $ NOP $ ] .OPCODE[775] .REPEAT 1 [ ;CAM -- A COPY OF CAM WHICH HALTS IF IT DOESN'T SKIP. WOW ! FIXM1 $ D[MEM] ACSEL[AC] ALU[AC-D] COND[JCOND] JUMP[DOSKP1] C600 $ D[MEM] CURRENTLY-UNUSED[1] JUMP[.] $ ;;DSKWT -- DELAY UNTIL DISK NOT BUSY ; JUMP[DSKWT1] $ ;OPCODE 775 ; NOP $ ; NOP $ ; NOP $ ] .REPEAT 0 [ ILGIOT $ NOP $ ILGIOT $ NOP $ ] .OPCODE[777] ;OPCODE 777 --- MAKE IT A UUO ;;; JUMP[MUUO] $ UAOP1 $ ;Illegal instruction rather than an IOT. It's an ;easy thing to stumble upon in buggy programs (or ;hardware), being it is most common negative integers ;MSTART MSTRT1 BADPC ILDB1 ILDB2 IDPB1 IDPB2 ILDB3 LDB1 LDB5 LDB2 LDB4 DPB1 DPB5 DPB7 IDPB3 DPB2 DPB4 BIIH1 BIIH BII IBP1 IBT1 ;NON DISPATCH STUFF HERE .ORG[4000] ; INIT THINGS -- INITIALIZE MACHINE, POWER-UP COMES HERE. MSTART: JUMP[MSTRT1] $ ;to help operator start from switches (KEEP THIS SIMPLE -- MLB) .USE[NORMAL] MSTRT1: ;******* This code to be made a subroutine to allow machine resetting ******* ;******* to be done by auto-loading and via CONO APR,20000 TVR-Mar80 ******* .REPEAT 1 - CROCK [ ;$*$*$ This crock will shortly vanish! ;Set up vectors for unused devices 9JAN80 BO (23JAN MLB/TVR) ;This code fills the zeroth location of all the AMEM blocks with a vector to ;the address SPURIOUS-INTERRUPT, which should contain the handler for them. .ORG[7777] ;this is randomly here, it could be anywhere SPURIOUS-INTERRUPT: JUMP[.] $ ;here on spurious interrupts .RELOC D[CONST (SPURIOUS-INTERRUPT / 100)] ROT[6] DEST[Q] $ ;Put high 6 bits in Q ..LOW6 = (SPURIOUS-INTERRUPT \ 100) .IF ..LOW6 /= 0 [ ;assemble low order 6 bits if non-zero D[CONST ..LOW6] ALU[DORQ] DEST[Q] $ ] D[CONST 40] DEST[AR CLR-DEV-FROM-INTR] NORM $ ;init AR for device num ALU[Q] DEST[0] DEST-A-MEM NORM $ ;store vector D[AR] ALU[D-1] DEST[AR DEV-ADR] ;decrement dev adr COND[-OBUS<0] JUMP[. - 1] C550 $ ;and loop ];1 - CROCK ;The following code sets up the AMEM zero vectors for various random devices. ;this is a complete CROCK! The device reset subroutines should do this!! ;I plan to fix this soon (when I have time, ha ha) -- MLB 23JAN80 ;$*$*$ Fix this soon. TVR-Apr80 D[CONST 20] ROT[6] DEST[Q CLR-DEV-FROM-INTR] NORM $ .DEFINE AMLD2 [ DEV ALOC VAL ] [ D[CONST DEV] DEST[DEV-ADR] NORM $ D[CONST VAL] ALU[DORQ] DEST-A-MEM DEST[ALOC] NORM $ ] AMLD2 [ 1 0 62 ] ; INTERRUPTS FROM DEV 1 (SWITCHES) GO TO 2062 D[CONST 21] ROT[6] DEST[Q] NORM $ ;;; AMLD2 [ 4 0 30 ] ; INTERRUPTS FROM DEV 4 GO TO 2130 [Now set at CTYRST] AMLD2 [ 5 0 34 ] ; INTRS FROM DEV 5 GO TO 2134 AMLD2 [ 6 0 41 ] ; INTS FROM DEV 6 GO TO 2141 AMLD2 [ 7 0 50 ] ; INTS FROM DEV 7 GO TO 2150 AMLD2 [ 10 0 56 ] ; INTS FROM DEV 10 GO TO 2156 .REPEAT DLS [ AMLD2 [ DLSDEV 0 37 ] ; DLS GOES TO 2137 ];DLS ;; the IMP reset code takes care of this for itself!! ;;; Moved code to set MAP-DISP to MAPRST (due to lack of space between ;;; 4000:4777). TVR-Apr80 ALU[0] DEST[CRYOV] NORM $ ALU[0] DEST[CLR-MI-ERR] NORM $ D[CONST 0] DEST[3] SPEC[A-MEM-APR&DEST-A-MEM] NORM $ JUMP[RESLOP] NORM $ BADPC: BADLOC $ ;------------------------------------------------------------------------------ ;$*$*$* THIS JUNK HAS GOT TO MOVE! TVR-Apr80 ; ;Some of it also needs commenting but this must be postponed until after CCRMA ;merge. ;------------------------------------------------------------------------------ .USE[AREA260] .PAIR ;Goes to second if HALF is not set ILDB1: D[AR] ROT[14] MASK[6] DEST[MASKR] JUMP[ILDB2] NORM $ ;Extract S field. Being HALF was set, don't increment D[AR] ROT[14] MASK[6] DEST[AR MASKR] COND[BYTE-OVF] PUSHJ[IBT1] NORM $ ;Extract S field. Increment word if byte overflow will happen D[AR] ROT[36] ALU[Q-D] DEST[Q AR MEMSTO] -MA-AC JUMP[. + 2] NORM $ ;SUB S FROM P ;Increment byte pointer, no overflow possible now ;Store into memory, check for store into AC ACSEL[MA] D[MEM] DEST[AC] CYLEN[MEMSTO] $ ;Store is into an AC, write it there. ILDB2: ALU[Q] DEST[MA] COND[-MEM-IDX-IND] LBJUMP[ILDB3] NORM $ ;Fetch data, perhaps. Maybe also do indexing or indirection .PAIR IDPB1: D[AR] ROT[14] MASK[6] DEST[MASKR] JUMP[IDPB2] NORM $ D[AR] ROT[14] MASK[6] DEST[AR MASKR] COND[BYTE-OVF] PUSHJ[IBT1] NORM $;GET S FLD, OVFL? D[AR] ROT[36] ALU[Q-D] DEST[Q AR MEMSTO] COND[-MA-AC] JUMP[. + 2] NORM $;SUB S FROM P ACSEL[MA] D[MEM] DEST[AC] CYLEN[MEMSTO] $ IDPB2: ALU[Q] DEST[MA] COND[-MEM-IDX-IND] LBJUMP[IDPB3] NORM $ .PAIR ;Goes to second if not indexing or indirecting ILDB3: MAPF[NORM-RD] PUSHJ[BIIH] NORM $;HANDLE IDX-IND MAPF[BYTE-ILD] ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] JUMP[LDB2] CYLEN[FIXM] $ ;Finish read of data word, then go extract byte .USE[AREA262] .PAIR ;Goes to second if not indexing or indirecting LDB1: MAPF[2] PUSHJ[BII] NORM $ LDB5: FIXM1 $ ;Also gets here from XBY13 D[AR] ROT[14] MASK[6] DEST[MASKR] SHORT $ ;GET S FLD SPEC[CLR-HALF] D[CONST 44] DEST[Q] SHORT $ D[AR] ROT[6] MASK[6] ALU[Q-D] DEST[Q ROTR] SHORT $ ;SUB P FLD FROM 44 D[AR] ROT[12.] MASK[6] ALU[Q-D] COND[-OBUS<0] JUMP[LDB4] C550 $ ;Also, subtract S field. If result is positive, then byte ;of size S fits with at least P bits remaining in the right ;side of the word ALU[Q] DEST[MASKR] JUMP[LDB4] NORM $ ;Byte does not fit!!! We want only the stuff to the left ;of postion P, which is 36.-P bits, coincidentally, the same ;size as the rotation ;S field is already set up. Set up P field and extract data from word. LDB2: SPEC[CLR-HALF] D[CONST 44] DEST[Q] SHORT $ D[AR] ROT[6] MASK[6] ALU[Q-D] DEST[ROTR] SHORT $ ;SUB P FLD FROM 44 LDB4: D[MEM] ACSEL[AC] ROT[R] MASK[R] SPEC[MA_PC] DEST[MA AC] JUMP[MAIN1] NORM $; DO THE LDB .PAIR DPB1: MAPF[2] PUSHJ[BII] NORM $ DPB5: ;Also gets here from XBY13 ;;; FIXM2 $ ;Wrong thing for WAITS. MAPF[BYTE-IDP] CYLEN[FIXM] ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-WRT] JUMP[DPB7] $ ;KA/KL set half flag even on DPB. They would also set read ;failure, not write, in the case of not in map; but we don't ;have time to be particular. TVR-Apr80 .USE[NORMAL] DPB7: D[AR] ROT[12.] MASK[6] DEST[MASKR] SHORT $ ;Fetch S field. SPEC[CLR-HALF] D[AR] ROT[6] MASK[6] DEST[Q ROTR] SHORT $ ;Fetch P field. D[CONST 44] ALU[D-Q] DEST[Q] SHORT $ ;Calculate 36-P, which is maximum number of bits in this byte D[AR] ROT[12.] MASK[6] ALU[Q-D] COND[-OBUS<0] JUMP[DPB4] C550 $ ;Does this byte fit? I.e. 36-P-S is non-negative. If so, ;use this mask field ALU[Q] DEST[MASKR] JUMP[DPB4] NORM $ ;Setup mask which is everything to the left of the position ;designated by P. .USE[AREA266] .PAIR IDPB3: MAPF[2] PUSHJ[BIIH] NORM $;HANDLE IDX-IND MAPF[BYTE-IDP] CYLEN[FIXM] ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-WRT] $ D[AR] ROT[14] MASK[6] DEST[MASKR] SHORT $ DPB2: SPEC[CLR-HALF] D[AR] ROT[6] MASK[6] DEST[Q ROTR] SHORT $ DPB4: D[2] MASK[R] ACSEL[AC] ALU[D&AC] DEST[AR] SHORT $;GET BYTE D[MEM] DEST[Q] SHORT $; GET DEST WORD D[2] MASK[R] ROT[R] ALU[-D&Q] DEST[Q] SHORT $;CLR DEST BYTE D[AR] ROT[R] ALU[DORQ] DEST[MEMSTO] MEMST $;DO IT .DEFINE BIIMAC[BIMAPF BIIH BIIH1] [ D[AR] ROT[18.] MASK[4] DEST[AC-SEL] COND[OBUS=0] JUMP[BIIH1] C550 $ ;IDX FLD D[MA] ACSEL[REG] MASK[18.] ALU[D+AC] DEST[MA] SHORT $ ;DO INDEXING D[AR] ROT[16] MASK[1] MAPF[2] COND[OBUS=0] POPJ CYLEN[C500] $ ;LEAVEIF NO IND BIIH1: ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[BIMAPF] CYLEN[FIXM] $ D[MEM] MASK[27] DEST[Q MA] COND[-MEM-IDX-IND] POPJ CYLEN[C500] $ ;GET INDIRECT WORD, LEAVE IF NO MORE IND OR IDX D[AR] ROT[14] MASK[14] DEST[AR] MAPF[2] NORM $ D[AR] ROT[30] ALU[DORQ] DEST[Q AR] COND[-INTRPT] JUMP[BIIH] NORM $ ;Loop if no interrupt is waiting. PUSHJ[SETHLF] NORM $ ;Intrpt. waiting. Set HALF (BIS) flag in PC. D[PC] ALU[D-1] DEST[PC] NORM JPOP[MAIN] $ ;Back up PC (so instr. will be re-executed) and take intrpt. ] .USE[AREA264] BIIH: BIIMAC [BYTE-IND BIIH BII1] .USE[NORMAL] BII: BIIMAC [NORM-RD BII BII2] .PAIR ;Skip if AC=0 IBP1: UAOP1 $ ;Non-zero AC implies ADJBP. We don't, yet. D[AR] ROT[14] MASK[6] DEST[AR] COND[BYTE-OVF] PUSHJ[IBT1] NORM $;GET S FLD, OVFL? ;Zero AC. Do ordinary increment byte pointer. ;PUSHJ if we are about to overflow a word. D[AR] ROT[36] ALU[Q-D] DEST[Q MEMSTO] MEMST $ ;Finish updating byte position part of pointer ;Increment byte pointer which crosses a word boundary IBT1: D[MASK 36] ALU[D&Q] DEST[Q] SHORT $ D[CONST 44] ROT[36] ALU[D+Q+1] DEST[Q] POPJ NORM $ ;NEW P FLD OF 44, ADD 1 TO ADR ;IMUL1 IMUL2 IMUL3 MUL1 MUL2 MUL3 DOIMUL MSETOV DOMMUL DOMUL DOMUL1 DOMUL4 IDIV1 IDIV2 IDIV3 DIV1 DIV2 DIV3 DODDIV DODIV DODIV1 DODIV3 DODIV2 STOVFQ DODIV4 DODIV6 DODIV5 IMUL1: ALU[0] DEST[AR O_AC] PUSHJ[DOIMUL] NORM $ ;0 TO AC,AC TO AR ALU[Q] DEST[AC] JUMP[MAIN] NORM $ IMUL2: ALU[0] DEST[AR O_AC] PUSHJ[DOIMUL] NORM $ ;0 TO AC D[AR] DEST[AC] NORM $ ALU[Q] DEST[MEMSTO] MEMST $ IMUL3: ALU[0] DEST[AR O_AC] PUSHJ[DOIMUL] NORM $ ALU[Q] DEST[AC MEMSTO] MEMST $ MUL1: ALU[0] DEST[AR O_AC] PUSHJ[DOMMUL] NORM $ ACSEL[AC+1] ALU[Q] DEST[AC] JUMP[MAIN] NORM $ MUL2: ALU[0] DEST[AR O_AC] PUSHJ[DOMMUL] NORM $ D[AR] DEST[O_AC MEMSTO] MEMST $ MUL3: ALU[0] DEST[AR O_AC] PUSHJ[DOMMUL] NORM $ ACSEL[AC+1] ALU[Q] DEST[AC] NORM $ ALU[AC] DEST[MEMSTO] MEMST $ DOIMUL: PUSHJ[DOMUL] NORM $ ALU[AC] COND[OBUS=0] POPJ CYLEN[C500] $; NO OV IF 0 ALU[NOTAC] COND[OBUS=0] POPJ CYLEN[C500] $; NO OV IF -1 MSETOV: D[PC] DEST[AC] SHORT $; GET FLAGS MSTOV1: D[CONST 1] ROT[43] ALU[DORAC] DEST[CRYOV] NORM POPJ $; SET OV DOMMUL: D[AR] ALU[D#Q] COND[-OBUS=0] JUMP[DOMUL] CYLEN[C500] $; NO OV IF DIFF OPERS D[CONST 1] ROT[43] ALU[D#Q] COND[-OBUS=0] JUMP[DOMUL] CYLEN[C500] $; J IF NOT -2**35 PUSHJ[MSETOV] NORM $;SET OV ALU[0] DEST[AC] SHORT $ DOMUL: D[CONST 42] LLOAD NORM $ ;LOOP 35 TIMES DOMUL1: D[AR] ALU[MULAC+D] DEST[D4] MASK[3] LOOP[DOMUL1] NORM $ ;SHIFT, END-COND MUL; SOJGE, SH RT ;This shifts right, with the low order bit of the partial ;product being saved in Q. At the same time, shift out of Q ;a bit of the multiplier (and somehow??? the hardware uses this ;to decide whether to add or not???) ;MASK field specifies what gets shifted into AC, in this case, ;(ALU OV) XOR (-OUT<0) D[AR] ALU[MULAC+D] DEST[D4] MASK[3] COND[-Q0-35] JUMP[. + 2] CYLEN[C450] $ ;J IF QUOT WAS + ;Do last step of multiply. Jump on sign of multiplier(?) D[AR] ALU[MULAC-D] DEST[D7] JUMP[. + 2] NORM $ ; DEST AC SH LFT, ALU=1, ALU S=0 ;Multiplier was positive... ???: Shift left to make properly ;signed result, with low order bit coming from Q0 (i think???) ALU[SH-AC] DEST[D7] NORM $ ;DEST AC SH LFT ;SINCE DEST IS >3, ALU[QORAC] IS ALU[AC] ;Multiplier was negative... ??? ALU[AC] COND[OBUS<0] LBJUMP[DOMUL4] CYLEN[C500] $ ;Decide what sign should be in the low order result. .PAIR DOMUL4: D[MASK 35.] ALU[D&Q] DEST[Q] POPJ NORM $ ;Positive. Turn off Q0, which was copied into AC35. D[CONST 1] ROT[35.] ALU[DORQ] DEST[Q] POPJ NORM $ ;Negative. Set Q0 so the number is negative (Q0 was copied into ;AC35). CCC1 = SHORT $ ;Apparently used as a NO-OP for macros below. TVR-Apr80 MEMST1 = MEMST $ ;Store to memory. (Cause macro expansion now, rather ;than in macro call.) .DEFINE DMACFN [AA A2 D1 D2 OP1] [ ALU[AA] D[AR] DEST[O_AC AR] SHORT $ ACSEL[AC+1] D[AR] ALU[A2] DEST[D1 D2] OP1 $ ALU[AC] DEST[MEMSTO] MEMSTMA $ ] .DEFINE DMAC2 [] [ D[MEM] ALU[D#AC] DEST[AR] PUSHJ[DODDIV] NORM $ ] .DEFINE DMAC1 [] [ .PAIR ALU[-1] DEST[AC] JUMP[. + 2] NORM $ ALU[0] DEST[AC] SHORT $ D[MEM] ALU[D#AC] DEST[AR] SHORT $ D[AR] ROT[1] MASK[1] DEST[IR-ADR] SHORT $ ALU[Q] DEST[AR] PUSHJ[DODIV] NORM $ ] IDIV1: DMAC1 DMACFN[Q D AC MA DOM1] IDIV2: DMAC1 DMACFN[D Q MEMSTO AR MEMST1] IDIV3: DMAC1 DMACFN[Q D AC 0 CCC1] DIV1: DMAC2 DMACFN[Q D AC MA DOM1] DIV2: DMAC2 DMACFN[D Q MEMSTO AR MEMST1] DIV3: DMAC2 DMACFN[Q D AC 0 CCC1] DODDIV: D[AR] ROT[1] MASK[1] DEST[IR-ADR] SHORT $ ALU[SH-AC] DEST[AR D5] MASK[1] NORM $ D[AR] MASK[1] COND[OBUS=0] JUMP[. + 2] C550 $ D[CONST 1] ROT[43] ALU[DORQ] DEST[Q] JUMP[. + 2] NORM $ D[MASK 43] ALU[D&Q] DEST[Q] NORM $ ;------------------------------------------------------------------------------ ; ; Single Precision Divide (and continuation of double precision) ; ; (Reminder: Quotient, Remainder = Dividend / Divisor) ; ;Where we get here: ; MEM 36 bit signed divisor ; AC High order dividend (0 or -1 for single precision) ; Q Low order dividend ; IR<35> Sign of dividend XOR sign of divisor ; AR Sign of dividend and original contents of AC ; ;------------------------------------------------------------------------------ DODIV: D[MEM] COND[-OBUS<0] JUMP[DODIV1] C550 $ ;Jump if divide by positive number D[MEM] ALU[0-D] DEST[HOLD] SHORT $ ;Take absolute value DODIV1: ALU[AC] COND[-OBUS<0] JUMP[DODIV2] CYLEN[C450] $ ;Check sign of high order word. If positive, we're ready to go ALU[0-Q] DEST[Q] COND[OBUS=0] JUMP[DODIV3] CYLEN[C500] $ ;Double precision negate, low order word ALU[NOTAC] DEST[AC] JUMP[DODIV2] NORM $ ;High order word, no carry DODIV3: ALU[0-AC] DEST[AC] NORM $ ;High order word, with carry DODIV2: D[CONST 44] LLOAD NORM $ ;LOOP 37 TIMES ;Now have: ; MEM Absolute value of divisor ; AC Absolute value of high order dividend ; Q Absolute value of low order dividend ; R Repeat count for division D[MEM] ALU[AC-D] COND[OBUS<0] JUMP[DODIV7] C550 $ ;Jump if not no divide case D[PC] DEST[AC] SHORT $ ;Get ready to set flags D[CONST 1] ROT[23.] ALU[DORAC] DEST[AC] PUSHJ[MSTOV1] NORM $ ;Set no divide D[AR] DEST[AC] POPJ NORM $ ;Fix clobbered AC ;$*$*$* NORMAL area runs of space for now. TVR-Apr80 .USE[AREA216] DODIV7: NORM PUSHJ[DODIV4] $ D[AR] COND[-OBUS<0] JUMP[. + 2] C550 $; J IF DIVIDEND WAS + ALU[0-AC] DEST[AC] SHORT $ D[IR] MASK[1] COND[OBUS=0] POPJ C550 $ ;LEAVE IF RESULT SHOULD BE + ALU[0-Q] DEST[Q] POPJ NORM $ ;On completion: ; MEM Absolute value of divisor ; AC Remainder ; Q Quotient ; AR<0> Sign of dividend ; IR<35> Sign of dividend .QUAD DODIV4: D[MEM] ALU[DIVAC-D] DEST[D6] MASK[3] COND[OBUS<0] SLOOP[DODIV4] C600 $ ALU[SH-AC] DEST[D5] MASK[0] JUMP[DODIV6] NORM $ ; RE-SHIFT REMAINDER D[MEM] ALU[DIVAC+D] DEST[D6] MASK[3] COND[OBUS<0] SLOOP[DODIV4] C600 $ ALU[SH-AC] DEST[D5] MASK[0] NORM $ ;end of .QUAD DODIV6: D[CONST 1] ROT[43] ALU[D#AC] DEST[AC] COND[-OBUS<0] C550 POPJ $ ;ADJUST REM SIGN, CHECK IT D[MEM] ALU[D+AC] DEST[AC] NORM POPJ $ ;ADJUST REM. .USE[NORMAL] ;JFFO1 JFFO2 JFFO3 JFFO5 JFFO4 ROTDO BIGLSH LSHPDO LSHDO LSHDO1 ASHDO1 BIGASH SETOV1 ASHDO ASHDOP BIGAS2 ASHC1 ASHC8 ASHC6 ASHC9 ASHC4 ASHC2 ASHC7 ROTC1 ROTC2 LSHC1 LSHC2 SJMAIN PUSH1 POP1 POPJ1 PUSHJ1 JFFO1: ACSEL[AC+1] ALU[0] DEST[AC] JUMP[MAIN] NORM $ JFFO2: D[AR] ROT[6] MASK[6] COND[-OBUS=0] JUMP[JFFO3] C550 $ D[AR] ROT[6] DEST[AR] NORM $ D[CONST 6] ACSEL[AC+1] ALU[AC+D] DEST[AC] JUMP[JFFO2] NORM $ JFFO3: D[AR] COND[OBUS<0] JUMP[JFFO4] C550 $ JFFO5: ACSEL[AC+1] ALU[AC+1] DEST[AC] NORM $ D[AR] ROT[1] DEST[AR] COND[-OBUS<0] JUMP[JFFO5] C550 $ JFFO4: D[IR] DEST[PC MA] JUMP[MAIN1] NORM $; JUMP .DEFINE SH2ND [ TYP DST1 DST2 DST3 ] [TYP`PLS: D[CONST 44] ALU[Q-D] COND[OBUS18] JUMP[DST3] C600 $ D[CONST 44] ALU[Q-D] DEST[Q ROTR] JUMP[DST1] NORM $ TYP`NEG: D[MASK 22] ROT[10] ALU[DORQ] DEST[Q ROTR] NORM $ TYP`NN1: D[CONST 44] ALU[D+Q] DEST[Q ROTR] COND[-OBUS18] JUMP[TYP`DO] C600 $ JUMP[DST2] NORM $ ] .USE[AREA270] SH2ND [ROT ROTPLS ROTNN1 ROTDO] ROTDO: ACSEL[AC] ALU[AC] DEST[AR] SHORT $ D[AR] ROT[R] ACSEL[AC] SPEC[MA_PC] DEST[AC MA] JUMP[MAIN1] NORM $ SH2ND [LSH BIGLSH BIGLSH LSHPDO] .USE[AREA272] BIGLSH: ACSEL[AC] ALU[0] SPEC[MA_PC] DEST[AC MA] JUMP[MAIN1] NORM $ LSHPDO: D[CONST 44] ALU[D-Q] DEST[MASKR] SHORT $ D[2] MASK[R] ALU[D&AC] ACSEL[AC] DEST[AR] SHORT $ D[AR] ROT[R] ACSEL[AC] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ LSHDO: ALU[Q] DEST[MASKR] SHORT $ ALU[AC] ACSEL[AC] DEST[AR] SHORT $ LSHDO1: D[AR] MASK[R] ROT[R] SPEC[MA_PC] DEST[AC MA] ACSEL[AC] JUMP[MAIN1] NORM $ ASHDO1: ALU[Q] DEST[MASKR] JUMP[LSHDO1] NORM $ .USE[NORMAL] SH2ND [ASH BIGASH BIGAS2 ASHDOP] BIGASH: ALU[AC] ACSEL[AC] COND[OBUS=0] JUMP[MAIN] CYLEN[C450] $ D[CONST 1] ROT[43] ACSEL[AC] ALU[D&AC] DEST[AC] SHORT $ D[PC] DEST[Q] SHORT $ SETOV1: D[CONST 1] ROT[43] ALU[DORQ] DEST[MA CRYOV] SPEC[MA_PC] NORM JUMP[MAIN1] $ ASHDO: ACSEL[AC] ALU[AC] DEST[AR] COND[-OBUS<0] JUMP[ASHDO1] CYLEN[C500] $ D[CONST 44] ALU[D-Q] DEST[MASKR] SHORT $ D[2] MASK[R] ROT[R] DEST[Q] SHORT $ D[AR] ROT[R] ALU[DORQ] SPEC[MA_PC] DEST[AC MA] ACSEL[AC] JUMP[MAIN1] NORM $ ASHDOP: D[CONST 43] ALU[D-Q] DEST[MASKR] SHORT $ ALU[Q] DEST[IR-ADR] SHORT $; SAVE SH AMT D[CONST 1] ROT[43] ACSEL[AC] ALU[D&AC] DEST[Q] SHORT $ ;GET SIGN BIT D[2] MASK[R] ACSEL[AC] ALU[D&AC] DEST[AR] SHORT $ D[AR] ROT[R] ACSEL[AC] ALU[DORQ] DEST[O_AC AR] SHORT $ D[IR] ALU[D+1] DEST[MASKR] SHORT $ D[AR] ROT[R] DEST[Q] SHORT $ D[2] MASK[R] ROT[43] ALU[D&Q] DEST[Q] COND[OBUS=0] JUMP[MAIN] C550 $ D[2] MASK[R] ROT[43] ALU[D#Q] COND[OBUS=0] JUMP[MAIN] C550 $ D[PC] DEST[Q] JUMP[SETOV1] NORM $ BIGAS2: ACSEL[AC] ALU[AC] COND[-OBUS<0] JUMP[BIGLSH] CYLEN[C450] $ ACSEL[AC] ALU[-1] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ASHC1: D[CONST 1] ROT[43] ALU[D&AC] ACSEL[AC] DEST[HOLD] NORM $ ; SAVE SIGN BIT D[IR] MASK[18.] COND[OBUS18] JUMP[ASHC2] C550 $ D[IR] MASK[10] COND[OBUS=0] JUMP[MAIN] C550 $ ALU[0] ACSEL[AC+1] DEST[AC] SHORT $ D[IR] MASK[10] ALU[D-1] LLOAD NORM $ ASHC8: ALU[SH-AC] DEST[D6] MASK[1] ACSEL[AC] NORM $ ACSEL[AC] D[MEM] ALU[D#AC] COND[OBUS<0] JUMP[ASHC9] C550 $ ASHC6: LOOP[ASHC8] NORM $ D[PC] ACSEL[AC+1] ALU[DORAC] DEST[CRYOV] JUMP[ASHC7] NORM $ ASHC9: D[CONST 1] ROT[43] ACSEL[AC+1] DEST[AC] JUMP[ASHC6] NORM $ .DEFINE SHLOOP [SHTYP DIR] [ D[IR] MASK[10] ALU[D-1] LLOAD NORM $ ALU[SH-AC] DEST[DIR] MASK[SHTYP] ACSEL[AC] LOOP[.] NORM $ ] ASHC4: D[MEM] DEST[Q] SHORT $ D[AR] ROT[43] MASK[43] ALU[DORQ] ACSEL[AC+1] DEST[AC] NORM $ D[MASK 43] ACSEL[AC] ALU[D&AC] DEST[AC] SHORT $ ACSEL[AC] ALU[QORAC] DEST[AC] JUMP[MAIN] NORM $ ASHC2: D[IR] ALU[0-D] DEST[IR-ADR] NORM $ SHLOOP [ 1 D4 ] ASHC7: ALU[Q] DEST[AR] JUMP[ASHC4] NORM $ .USE[AREA274] ROTC1: D[IR] ALU[0-D] DEST[IR-ADR] JUMP[ROTC2] NORM $ D[IR] COND[OBUS=0] MASK[10] JUMP[MAIN] C550 $ SHLOOP[ 0 D6 ] ALU[Q] DEST[AC] ACSEL[AC+1] JUMP[MAIN] NORM $ ROTC2: SHLOOP[ 0 D4 ] ALU[Q] DEST[AC] ACSEL[AC+1] JUMP[MAIN] NORM $ .PAIR LSHC1: D[IR] MASK[18.] ALU[0-D] DEST[IR-ADR] JUMP[LSHC2] NORM $ D[IR] MASK[10] COND[OBUS=0] JUMP[MAIN] C550 $ SHLOOP [ 2 D6 ] ALU[Q] DEST[AC] ACSEL[AC+1] JUMP[MAIN] NORM $ .USE[AREA272] debuguse = . ;See if it is still losing : 2735 ;%$@#&@# SLOEXP didn't redefine AREA272 properly!!! $*$*$* LSHC2: SHLOOP[ 2 D4 ] ALU[Q] DEST[AC] ACSEL[AC+1] JUMP[MAIN] NORM $ .USE[AREA202] SJMAIN: ACSEL[MA] D[MEM] DEST[AC] $ D[IR] DEST[MA PC] JUMP[MAIN1] $ .USE[NORMAL] PUSH1: D[CONST 1,,1] ALU[D+AC] DEST[AC MA] COND[CRY0] JUMP[PDLO2] C600 $ D[AR] DEST[MEMSTO] MEMSTMA $ POP1: D[MEM] DEST[AR] SHORT $ D[IR] MASK[18.] DEST[MA] SHORT $ D[AR] DEST[MEMSTO] MEMST $ POPJ1: D[MEM] MASK[18.] DEST[PC MA] JUMP[MAIN1] NORM $ PUSHJ1: MAPF[MASTO] D[IR] MASK[18.] SPEC[CLR-HALF] DEST[PC] MEMST $ ;BLTA2 BLT1 BLT7 BLT5 BLT3 BLT2 BLT9 BLT4 BLT6 BLT8 BLTA3 BLTL1 BLTA4 BLTA1 BLTAL2 BLTA10 BLTL2 BLTA12 ANDCA1 ANDCA2 ANDCA3 LOG2 LOG3 ORCM2 ORCM3 .PAIR BLTA2: ACSEL[AC] ALU[AC] DEST[AR MA] JUMP[BLTA3] NORM $ ;SRC IS AC GET DEST ADR BLT1: D[PC] DEST[O_AC AR] ACSEL[AC] SHORT $ D[AR] MASK[18.] DEST[Q PC] SHORT $ D[IR] MASK[18.] ALU[D-Q] DEST[Q] LLOAD NORM $;GET COUNT ALU[Q] COND[OBUS<0] JUMP[BLT4] CYLEN[C450] $ ; J IF END PRECEDES STRT BLT7: D[AR] MASK[18.] ROT[18.] DEST[Q MA AR] SHORT $; FETCH FIRST WORD BLT5: DEST[FIXMAC-MAPF-RD] MAPF[BLT-RD] JUMP[BLT2] CYLEN[FIXM] $ BLT3: DEST[FIXMAC-MAPF-RD] MAPF[BLT-RD] SPEC[PC+1] CYLEN[FIXM] $ BLT2: D[MEM] SPEC[MA_PC] DEST[MEMSTO MA] COND[INTRPT] JUMP[BLT6] NORM $ ALU[Q+1] DEST[Q AR MA] LOOP[BLT3] MAPF[BLT-WRT] CYLEN[MEMSTO] $ BLT9: D[PC] MASK[18.] ACSEL[AC] DEST[O_AC PC] NORM $ ACSEL[AC] D[IR] MASK[18.] ALU[AC-D] COND[-OBUS<0] JUMP[MAIN] C550 $ ;J IF DONE ACSEL[AC] ALU[AC+1] DEST[AC] SHORT $ D[IR] ACSEL[AC] ALU[D-AC] LLOAD NORM $ ;GET COUNT D[PC] ACSEL[AC] DEST[O_AC PC] SHORT $ ALU[Q] DEST[MA] JUMP[BLT5] NORM $ BLT4: ALU[0] LLOAD NORM $ JUMP[BLT7] NORM $ BLT6: ALU[Q+1] DEST[Q AR] LOOP[BLT8] MAPF[BLT-WRT] CYLEN[MEMSTO] $ JUMP[BLT9] $ BLT8: ACSEL[AC] ALU[AC-1] DEST[AC] SPEC[PC+1] NORM $ ACSEL[AC] D[PC] MASK[18.] DEST[O_AC PC] SHORT $ D[AR] ROT[18.] SPEC[LEFT] ALU[DORAC] ACSEL[AC] DEST[AC] SHORT $ DISP[2320] SPEC[PC+1-IF&] CYLEN[DISP] $ BLTA3: D[AR] ROT[18.] DEST[AC-SEL] SHORT $ ;GET SRC ADR D[IR] MASK[18.] DEST[Q] SHORT $ D[MA] MASK[18.] ALU[Q-D] DEST[Q] LLOAD NORM $ ALU[Q] COND[OBUS<0] PUSHJ[BLTA4] CYLEN[C450] $ D[AR] ROT[18.] MASK[18.] ALU[D+Q] DEST[Q] SHORT $ D[MASK 30] ROT[4] ALU[D&Q] COND[-OBUS=0] JUMP[BLTA10] C550 $;J IF SRC LEAVES AC'S BLTL1: ACSEL[REG] ALU[AC] DEST[MEMSTO] NORM $ D[MA] ALU[D+1] DEST[MA A-MEM-CNTR&INC] MAPF[BLT-WRTA] LOOP[BLTL1] CYLEN[MEMSTO] $ SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ BLTA4: ALU[0] DEST[Q] LLOAD NORM $ POPJ NORM $ BLTA1: D[MASK 16] ROT[26] ACSEL[AC] ALU[D&AC] COND[OBUS=0] JUMP[BLTA10] C550 $; DEST IS AC, J IF SRC AC? D[IR] ROT[40] MASK[16] COND[-OBUS=0] JUMP[BLTA10] C550 $;J IF FINAL DEST NOT AC ACSEL[AC] ALU[AC] DEST[AR AC-SEL] SHORT $;GET DEST ADR D[IR] MASK[18.] DEST[Q] SHORT $ D[AR] MASK[18.] ALU[Q-D] DEST[Q] LLOAD NORM $;GET COUNT ALU[Q] COND[OBUS<0] PUSHJ[BLTA4] CYLEN[C450] $;ADJUST IF CNT NEG. D[AR] ROT[18.] MASK[18.] DEST[MA] SHORT $;GET SRC ADR BLTAL2: DEST[FIXMAC-MAPF-RD AC] MAPF[BLT-RDA] D[MA] ALU[D+1] ACSEL[REG] CYLEN[FIXM] $ ACSEL[REG] D[MEM] DEST[O_AC MA A-MEM-CNTR&INC] LOOP[BLTAL2] NORM $ SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ BLTA10: ACSEL[AC] ALU[AC] DEST[AR] SHORT $ BLTL2: D[AR] ROT[18.] MASK[18.] DEST[MA] SHORT $;GET WORD ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[BLT-RDA] CYLEN[FIXM] $ D[MEM] DEST[HOLD Q] SHORT $ D[AR] MASK[18.] DEST[MA STRT-WRT] SHORT $ MAPF[BLT-WRTA] COND[-MA-AC] JUMP[. + 2] C500 $ ALU[Q] ACSEL[MA] DEST[AC] SHORT $ D[AR] MASK[18.] DEST[Q] NORM $ D[IR] MASK[18.] ALU[Q-D] MAPF[BLT-WRTA] COND[-OBUS<0] JUMP[MAIN] C600 $ D[CONST 1,,1] DEST[Q] NORM $ D[AR] ALU[D+Q] DEST[AR] JUMP[BLTL2] NORM $;*** TEST FOR INTERRUPT HERE? BLTA12: MEMST $ .USE[AREA276] ANDCA1: D[MEM] ACSEL[AC] ALU[D&Q] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ANDCA2: D[MEM] ALU[D&Q] DEST[MEMSTO] MEMST $ ANDCA3: D[MEM] ACSEL[AC] ALU[D&Q] DEST[AC MEMSTO] MEMST $ LOG2: ALU[NOTQ] DEST[MEMSTO] MEMST $ LOG3: ACSEL[AC] ALU[NOTQ] DEST[AC MEMSTO] MEMST $ ORCM2: ACSEL[AC] ALU[QORAC] DEST[MEMSTO] MEMST $ ORCM3: ACSEL[AC] ALU[QORAC] DEST[AC MEMSTO] MEMST $ .USE[NORMAL] ;SWINT NORSW NOSW RESW1 RESET RESET RESLOP DOHALT STPLOP STPLP1 NORSW2 RESW2 STRTSW CONSW DEPTSW DEPNSW DEPSW1 EXMTSW EXMNSW SETLTS EXMSW1 BRPNT MOVSS1 MOVNS1 HLLZS1 HRLZS1 HRRZS1 HLRZS1 HRAR HLAR HLLEM1 HRLEM1 HLREM1 HRREM1 HSMAIN HSMN1 HLLOS1 HRROS1 HLLES1 HRRES1 HLLES2 HMV HHS HLSZ HOR HRSZ HOL HRLM1 HLLM1 HLRM1 HRRM1 JRST1 JRST4 JRST5 JRST9 JRST8 JRST2 JRST3 JFCL1 JSR2 JSA1 JRA1 MUJSR MUJSP ; MUJSA MUJSYS MUJSM1 ;;;RESW1: .ORG[2062] ;*$*$* No REAL reason for this : 2062 ;SWITCH, AR & ECC INTERRUPTS COME HERE SWINT: DEST[CLR-DEV-FROM-INTR] SHORT $ ALU[0] DEST[DEV-ADR] SPEC[IOB-IN] SHORT $ D[IOD] DEST[AR] MAPF[4] CYLEN[IOB-IN] $ ;GET SW BITS D[AR] ROT[7] MASK[1] COND[-OBUS=0] JUMP[APDINT] C550 $ ;JUMP IF OVFL OR ECC INT D[CONST 15] ROT[1] DEST[Q] SPEC[IOB-OUT] SHORT $ D[AR] ROT[14] ALU[D&Q] MAPF[4] COND[OBUS=0] JUMP[NOSW] C550 $ ;CHECK FOR RELEVANT SW, & CLR FF. D[AR] ROT[10] MASK[1] COND[-OBUS=0] JUMP[RESW1] C550 $ ;J IF RESET SW NORSW: D[AR] ROT[13] MASK[1] COND[-OBUS=0] PUSHJ[EXMTSW] C550 $ ;PUSHJ IF EXAM THIS D[AR] ROT[11] MASK[1] COND[-OBUS=0] PUSHJ[DEPTSW] C550 $ ;PUSHJ IF DEPO THIS NOSW: SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ area206 = . ;Sigh... .RELOC RESW1: SPEC[IOB-IN] SHORT $ D[IOD] DEST[AR] CYLEN[IOB-IN] $ ;DOUBLE CHECK RESET SW D[AR] ROT[10] MASK[1] COND[OBUS=0] JUMP[NORSW] CYLEN[C650] $ ;DOUBLE CHECK RESET SW ;******* This code to be made a subroutine to allow machine resetting ******* ;******* to be done by auto-loading and via CONO APR,20000 TVR-Mar80 ******* .REPEAT F2SW [ RESET: D[CONST 0] DEST[IOD] SPEC[IOB-OUT] NORM $ ] ;END F2SW .REPEAT 1 - F2SW [ RESET: D[CONST 1] DEST[IOD] SPEC[IOB-OUT] NORM $ ] ;END 1 - F2SW ;*** Disable ECC interrupts on F3's????? MAPF[10] ALU[0] DEST[CRYOV] CYLEN[IOB-OUT] $ ;CLR MAP-IN-USE & PC FLAGS & AR INT ENBL, ETC. DEST[CLR-MI-ERR] JUMP[RESLOP] NORM $ RESLOP: ALU[0] DEST[HI-ABS-MA] NORM $ DEST[CLR-DEV-FROM-INTR] $ D[CONST 0] DEST[DEV-ADR] PUSHJ[APRRST] NORM $ D[CONST 1] DEST[DEV-ADR] PUSHJ[MAPRST] NORM $ D[CONST 4] DEST[DEV-ADR] PUSHJ[CTYRST] NORM $ D[CONST 10] DEST[DEV-ADR] PUSHJ[DSKRST] NORM $ .REPEAT WK [ D[CONST 24] DEST[DEV-ADR] PUSHJ[WKRST] NORM $ ] D[CONST 7] DEST[DEV-ADR] PUSHJ[TAPRST] NORM $ .REPEAT DLS [; 9 JAN 80 BO D[CONST DLSDEV] DEST[DEV-ADR] PUSHJ[DLSRST] NORM $ ];DLS .REPEAT VC [ ; 24 AUG 80 BO D[CONST VCDEV] DEST[DEV-ADR] PUSHJ[VCRST] NORM $ ] ; VC .REPEAT IMP [; 23JAN80 MLB D[CONST 16] DEST[DEV-ADR] PUSHJ[IMPRST] NORM $ ];IMP .REPEAT LPT [ .REPEAT STANSW [ D[CONST 15] DEST[DEV-ADR] PUSHJ[LPTRST] NORM $ ;Hardware is trapping to wrong place!!! ];.REPEAT STANSW D[CONST 35] DEST[DEV-ADR] PUSHJ[LPTRST] NORM $ ];LPT .REPEAT STANSW [;Mar80 TVR D[CONST 30] DEST[DEV-ADR] PUSHJ[PANRST] NORM $ D[CONST 30] DEST[DEV-ADR] PUSHJ[GRNRST] NORM $ ];REPEAT STANSW D[CONST 6] DEST[DEV-ADR] PUSHJ[CLKRST] NORM $ D[CONST 6] DEST[DEV-ADR] PUSHJ[TYMRST] NORM $ D[CONST 6] DEST[DEV-ADR] PUSHJ[PI-RESET] NORM $ DOHALT: DEST[CLR-DEV-FROM-INTR] NORM $ STPLOP: D[CONST 1] DEST[DEV-ADR] SPEC[IOB-IN] NORM $ MAPF[4] D[IOD] DEST[Q] CYLEN[IOB-IN] $ ALU[0] DEST[DEV-ADR] SHORT $ D[CONST 10] ALU[DORQ] DEST[IOD] SPEC[IOB-OUT] NORM $ MAPF[10] CYLEN[IOB-OUT] $; SET PROG HALT LIGHT ALU[0] DEST[DEV-ADR MA] SPEC[MA_PC] NORM $ FIXM1 SPEC[IOB-OUT] $ D[MEM] MAPF[6] CYLEN[LONG] $ SPEC[IOB-IN] NORM $ D[IOD] DEST[AR] MAPF[4] CYLEN[IOB-IN] $ D[AR] COND[OBUS<0] JUMP[BRPNT] C600 $; J IF BRK POINT SW SPEC[IOB-IN] NORM $ STPLP1: D[IOD] DEST[AR] MAPF[4] CYLEN[IOB-IN] $ ;GET SW BITS D[AR] ROT[10] MASK[1] COND[-OBUS=0] JUMP[RESW2] C550 $ ;J IF RESET SW D[AR] ROT[14] MASK[11] DEST[Q] NORM $ D[CONST 7] ROT[4] ALU[-D&Q] COND[OBUS=0] SPEC[IOB-IN] JUMP[STPLP1] C600 $; LOOP IF NO SW SPEC[IOB-OUT] NORM $ MAPF[4] CYLEN[IOB-OUT] $ ;CLR SW FF'S .DEFINE SWTEST [ RAMT DIS ADR ] [ D[AR] ROT[RAMT] MASK[1] COND[-OBUS=0] DIS [ ADR ] C550 $ ] NORSW2: SWTEST[4 JUMP CONSW] SWTEST[5 JUMP STRTSW] SWTEST[11 PUSHJ DEPTSW] SWTEST[12 PUSHJ DEPNSW] SWTEST[13 PUSHJ EXMTSW] SWTEST[14 PUSHJ EXMNSW] D[CONST 0] DEST[DEV-ADR] SPEC[IOB-IN] JUMP[STPLP1] NORM $ ;LOOP RESW2: SPEC[IOB-IN] SHORT $ D[IOD] DEST[AR] CYLEN[IOB-IN] $ ;DOUBLE CHECK RESET SW D[AR] ROT[10] MASK[1] COND[OBUS=0] JUMP[NORSW2] CYLEN[IOB-IN] $ ;DOUBLE CHECK RESET SW JUMP[RESET] NORM $ STRTSW: D[AR] MASK[23] DEST[PC] NORM $ CONSW: ALU[0] SPEC[MA_PC] DEST[MA HI-ABS-MA] NORM $ D[CONST 1] DEST[DEV-ADR] SPEC[IOB-IN] NORM $ MAPF[4] D[IOD] DEST[Q] CYLEN[IOB-IN] $ ALU[0] DEST[DEV-ADR] NORM $ D[CONST 7] ALU[D&Q] DEST[IOD] SPEC[IOB-OUT] NORM $ MAPF[10] CYLEN[IOB-OUT] $; CLEAR PROG HALT LIGHT ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[1] CYLEN[FIXM] $ D[MEM] DEST[IR-ALL AR MA] DISP[2074] SPEC[PC+1-IF] CYLEN[DISP] $ ; IGNORE STOP SW AND INTERRUPTS DEPTSW: D[AR] MASK[23] DEST[MA HI-ABS-MA] SPEC[IOB-IN] JUMP[DEPSW1] NORM $ DEPNSW: D[MA] ALU[D+1] DEST[MA] NORM SPEC[IOB-IN] $ DEPSW1: D[IOD] DEST[MEMSTO] MAPF[2] CYLEN[IOB-IN] $ MAPF[TEMP] COND[-MA-AC] POPJ CYLEN[MEMSTO] $ ACSEL[MA] D[MEM] DEST[AC] POPJ NORM $ EXMTSW: D[AR] MASK[23] DEST[MA HI-ABS-MA] JUMP[EXMSW1] NORM $ EXMNSW: D[MA] ALU[D+1] DEST[MA] JUMP[EXMSW1] NORM $ ;NOTE: This subroutine is called by DATAO PI, which displays in the lights SETLTS: FIXM1 $ ;Take page faults, if any. EXMSW1: ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[TEMP] CYLEN[FIXM] $ SPEC[IOB-OUT] NORM $ D[MEM] MAPF[2] CYLEN[LONG] POPJ $ BRPNT: D[AR] MASK[27] DEST[Q] NORM $ D[PC] MASK[27] ALU[D-Q] COND[-OBUS=0] JUMP[CONSW] C600 $ SPEC[IOB-IN] JUMP[STPLP1] NORM $ .USE[AREA276] MOVSS1: D[MEM] ROT[18.] ACSEL[AC] DEST[AC MEMSTO] MEMST $ MOVNS1: D[MEM] ALU[0-D] ACSEL[AC] DEST[AC MEMSTO] MEMST $ HLLZS1: ACSEL[MA] D[MEM] COND[AC=0] DEST[AC AR MA] SPEC[LEFT&MA_PC] LBJUMP[HSMAIN] NORM $ HRLZS1: ACSEL[MA] D[MEM] ROT[18.] COND[AC=0] DEST[AC AR MA] SPEC[LEFT&MA_PC] LBJUMP[HSMAIN] NORM $ HRRZS1: ACSEL[MA] D[MEM] MASK[18.] COND[AC=0] DEST[AC AR MA] SPEC[MA_PC] LBJUMP[HSMAIN] NORM $ HLRZS1: ACSEL[MA] D[MEM] ROT[18.] MASK[18.] COND[AC=0] DEST[AC AR MA] SPEC[MA_PC] LBJUMP[HSMAIN] NORM $ .USE[AREA342] HRAR: D[AR] MASK[18.] ALU[DORAC] ACSEL[AC] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ HLAR: D[AR] SPEC[LEFT&MA_PC] MASK[0] ALU[DORAC] ACSEL[AC] DEST[AC MA] JUMP[MAIN1] NORM $ HLLEM1: D[AR] MASK[0] SPEC[LEFT] DEST[MEMSTO] MEMST $ HRLEM1: D[AR] ROT[18.] MASK[0] SPEC[LEFT] DEST[MEMSTO] MEMST $ HLREM1: D[AR] ROT[18.] MASK[18.] DEST[MEMSTO] MEMST $ HRREM1: D[AR] MASK[18.] DEST[MEMSTO] MEMST $ .USE[AREA344] .PAIR HSMAIN: ACSEL[AC] D[AR] DEST[AC] NORM $ ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[1] JPOP[MAIN2] NORM $ .PAIR HSMN1: SPEC[MA_PC] DEST[MA] JUMP[MAIN1] CYLEN[MEMSTO] $ D[MEM] ACSEL[AC] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] CYLEN[MEMSTO] $ .PAIR HLLOS1: D[MASK 22] ALU[DORQ] DEST[MEMSTO] MEMST $ D[MASK 22] ALU[DORQ] DEST[MEMSTO AC] ACSEL[AC] MEMST $ .PAIR HRROS1: D[MASK 22] ROT[18.] ALU[DORQ] DEST[MEMSTO] MEMST $ D[MASK 22] ROT[18.] ALU[DORQ] DEST[MEMSTO AC] ACSEL[AC] MEMST $ .PAIR HLLES1: D[MASK 22] ROT[18.] ALU[D&Q] DEST[Q] COND[-AC=0] LBJUMP[HLLES2] NORM $ COND[-AC=0] LBJUMP[HLLOS1] NORM $ .PAIR HRRES1: D[MASK 22] ALU[D&Q] DEST[Q] COND[-AC=0] LBJUMP[HLLES2] NORM $ COND[-AC=0] LBJUMP[HRROS1] NORM $ .USE[AREA346] .PAIR HLLES2: ALU[Q] DEST[MEMSTO] MEMST $ ALU[Q] ACSEL[AC] DEST[MEMSTO AC] MEMST $ .PAIR HMV: JUMP[MAIN] NORM $ JUMP[MOVE] NORM $ .PAIR HHS: D[AR] ROT[18.] ALU[DORQ] DEST[MEMSTO] MEMST $ D[AR] ROT[18.] ALU[DORQ] ACSEL[AC] DEST[MEMSTO AC] MEMST $ .USE[AREA352] .PAIR HLSZ: SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ HOR: D[MASK 22] ACSEL[AC] ALU[DORAC] SPEC[MA_PC] DEST[MA AC] JUMP[MAIN1] NORM $ .PAIR HRSZ: SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ HOL: D[MASK 22] ACSEL[AC] ROT[18.] ALU[DORAC] SPEC[MA_PC] DEST[MA AC] JUMP[MAIN1] NORM $ .PAIR HRLM1: D[AR] ROT[18.] DEST[Q] NORM $ HLLM1: D[MEM] MASK[18.] ALU[DORQ] DEST[MEMSTO] MEMST $ .PAIR ;(??) Added TVR-Apr80 HLRM1: D[AR] ROT[18.] DEST[Q] NORM $ HRRM1: D[MEM] MASK[0] SPEC[LEFT] ALU[DORQ] DEST[MEMSTO] MEMST $ .USE[AREA350] .PAIR JRST1: ;10 bit on in AC field COND[USER] JUMP[MUUO] NORM $; ILLEGAL IF USER MODE ;10 bit off, or exec mode. Check 2 bit. D[IR] ROT[14] MASK[1] COND[-OBUS=0] JUMP[JRST2] C550 $ JRST4: ;If 1 bit on in AC field, set user mode D[IR] ROT[15] MASK[1] COND[-OBUS=0] JUMP[JRST3] C550 $ JRST5: ;If 4 bit on in AC field, act like stop switch D[IR] ROT[13] MASK[1] COND[-OBUS=0] JUMP[JRST9] C550 $ ;If 10 bit on in AC field, dismiss D[IR] ROT[12] MASK[1] COND[-OBUS=0] JUMP[PI-DISMISS] C550 $ JUMP[MAIN1] NORM SPEC[MA_PC] DEST[MA] $ ;4 bit on in AC field JRST9: COND[EXEC] JUMP[DOHALT] NORM $; HALT IF EXEC MODE MUUO1 $ ;Halting in user mode is illegal ;2 bit on in AC field JRST2: D[PC] DEST[Q] SHORT $ ;Flag restore. D[CONST 1] ROT[36] ALU[D&Q] DEST[Q] SHORT $ ;Don't let USER be cleared. D[AR] ALU[DORQ] DEST[Q] NORM $ ;Put in the new bits (but OR in the old USER) D[CONST 1] ROT[35. - 9.] ALU[-D&Q] DEST[CRYOV] JUMP[JRST4] NORM $ ;Don't let bit 9 be set (it is a sort of trap flag for PDL OV) .USE[AREA354] ;1 bit on in AC field, set user mode JRST3: D[CONST 1] ROT[36] DEST[Q] SHORT $ D[PC] ALU[DORQ] DEST[CRYOV] JUMP[JRST5] NORM $ JFCL1: D[AR] ROT[40] ALU[D&Q] COND[OBUS=0] JUMP[MAIN] C550 $;TEST SELECTED FLAGS D[AR] ROT[40] ALU[-D&Q] DEST[CRYOV] SHORT $;CLEAR FLAGS DOJUMP $ JSR2: D[MA] ALU[D+1] DEST[PC] SPEC[CLR-HALF] MAPF[STO] NORM $ ACSEL[MA] D[MEM] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ JSA1: D[MA] ALU[D+1] DEST[PC] SHORT $ D[AR] DEST[MEMSTO] MEMST $ JRA1: FIXM1 $ ACSEL[AC] D[MEM] DEST[AC] CYLEN[FIXM+1] $ D[IR] MASK[18.] DEST[PC MA] JUMP[MAIN1] NORM $ .USE[NORMAL] MUJSR: D[MEM] DEST[IR-ALL MA] NORM $; GET INSTR. D[AR] DEST[MEMSTO] COND[MA-AC] JUMP[JSR2] NORM $ D[MA] ALU[D+1] DEST[MA PC] MAPF[STO] SPEC[CLR-HALF] JUMP[MAIN1] CYLEN[MEMSTO] $ MUJSP: D[MEM] DEST[IR-ALL MA] NORM $; GET INSTR. D[AR] ACSEL[AC] DEST[AC] JUMP[JSP1] NORM $ MUJSA: D[MEM] DEST[IR-ALL MA] NORM $; GET INSTR. D[AR] ACSEL[AC] DEST[O_AC AR] JUMP[JSA1] NORM $ MUJSYS: D[MEM] DEST[IR-ALL MA] SHORT $ D[IR] ROT[33] MASK[11] COND[OBUS=0] JUMP[JSYS3] C550 $; J IF EX JSYS MUJSM1: ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[MAPFTR] CYLEN[FIXM] $ D[MEM] MASK[18.] DEST[PC] NORM $; JUMP TO RIGHT HALF D[MEM] ROT[18.] MASK[18.] DEST[MA] SHORT $; GET READY TO STORE D[AR] DEST[MEMSTO] MEMSTMA $ ;CTYDSP AREA51 CTYINT CTYIOT CTYDI CTYDO CTYCO CTYCI CTYCI2 CTYCI1 CTYCI9 CTYCI8 CTYCI3 CTYCO1 CTYCO3 CTYCO4 CTYCO5 CTYRST ctyrs1 AREA52 CTYCZ CTYCS ;------------------------------------------------------------------------------ ; ; CTY - Console Teletype Device 120 ; ;------------------------------------------------------------------------------ ; ;A-MEM Usage ; CTY-DISP = 0 ;Instruction and interrupt dispatch CTY-CONT = 1 ;Control bits for UART, etc. CTY-STATUS = 2 ;Firmware status ; ;*** Meanings of hardware bits should be documented here. ; ;MAPF values .REPEAT NTP [ TTY.DI = 0 ;read data TTY.WD = 12 ;write data TTY.WC = 14 ;write control ] ;NTP .REPEAT OTP [ TTY.DI = 0 ;read data TTY.WD = 4 ;write data TTY.WC = 10 ;write control ] ;OTP ;*$*$* This ORG is ready to be flushed. It only remains to test the code ; and merge the AREAs .ORG[5100] ;CTY IOT DISPATCH TABLE CTYDSP: ILGIOT $ ;BLKI NOP $ D[CTY-STATUS + 10] DEST[Q] SPEC[IOB-IN] NORM $ ;DATAI MAPF[TTY.DI] D[IOD] DEST[AR] JUMP[CTYDI] CYLEN[IOB-IN] $ ILGIOT $ ;BLKO NOP $ FIXM1 $ ;DATAO D[CTY-STATUS + 10] DEST[Q] JUMP[CTYDO] NORM $ ; GET CONI BITS D[CTY-STATUS + 10] MASK[7] DEST[Q] NORM $ ;CONO, GET CONI BITS D[IR] MASK[7] ROT[40] ALU[-D&Q] DEST[Q] JUMP[CTYCO] NORM $ ;CLR THE CLR BITS D[CTY-STATUS + 10] DEST[Q] PUSHJ[CTYCI] NORM SPEC[IOB-IN] $ ; CONI, GET BITS D[AR] DEST[MEMSTO] MEMST $ D[CTY-STATUS + 10] DEST[Q] PUSHJ[CTYCI] NORM SPEC[IOB-IN] $ ;CONSZ, GET BITS D[IR] MASK[18.] DEST[Q] JUMP[CTYCZ] NORM $ D[CTY-STATUS + 10] DEST[Q] PUSHJ[CTYCI] NORM SPEC[IOB-IN] $ ;CONSO, GET CONI BITS D[IR] MASK[18.] DEST[Q] JUMP[CTYCS] NORM $ ;$*$*$ We may not be able to afford this in the future... TVR-Apr80 LPTDSP: .REPEAT 1 - LPT [ .REPEAT 10 [ILGIOT $ NOP $ ];.REPEAT 10 ];.REPEAT 1 - LPT .REPEAT LPT [ ;Allocate space for LPT dispatch :. + 20 ];.REPEAT LPT AREA51: ;$*$*$ Start code from here for now. This should go away : 2130 ;CTY and 60 HZ CLOCK INTS COME HERE CTYINT: .REPEAT NTP [;With new tape controller, 60HZ clk shares DEV 4 w/ CTY. START-IN SHORT $ MAPF[5] D[IOD] ALU[NOTD] DEST[AR] C600 $ ;Read the NET interface status... D[AR] MASK[1] C550 -OBUS=0 JUMP[CLKINT] $ ;Is 60HZ clk requesting an int. ? Jump if so. NORM JUMP[CTYIN1] $ ;Else it is the CTY's turn. : 2144 ] ;NTP CTYIN1: D[CTY-STATUS + 10] DEST[Q] PUSHJ[CTYCI] NORM SPEC[IOB-IN] $ ; DO A CONI, GET BITS D[CTY-CONT + 10] MASK[11] DEST[IOD] SPEC[IOB-OUT] NORM $; DISABLE INTS MAPF[TTY.WC] CYLEN[IOB-OUT] D[CTY-STATUS + 10] MASK[3] DEST[Q AR] $ ; GET PI CHAN NORM DEST[CLR-DEV-FROM-INTR] JUMP[PIGEN] $;CAUSE INTR. ;$*$*$ This one is referenced off the MAP dispatch AREA52 = 5210 .USE[AREA52] .PAIR UIOTRP[MUUO] $ CTYIOT: IOTDIS [51] CTYDI: D[CONST 40] ALU[-D&Q] DEST-A-MEM DEST[CTY-STATUS] NORM $; CLR TTI FLAG D[CONST 10] ROT[3] DEST[Q] SHORT $ D[CTY-CONT + 10] ALU[DORQ] DEST[IOD] SPEC[IOB-OUT] SHORT $;CLR RCV. CHR MAPF[TTY.WC] CYLEN[IOB-OUT] $ D[CTY-CONT + 10] DEST[IOD] SPEC[IOB-OUT] SHORT $ MAPF[TTY.WC] CYLEN[IOB-OUT] $ D[AR] MASK[10] DEST[MEMSTO] MEMST $ CTYDO: D[MEM] DEST[IOD] SPEC[IOB-OUT] NORM $;SEND CHR. MAPF[TTY.WD] CYLEN[IOB-OUT] D[CONST 10] ALU[-D&Q] DEST[Q] $;CLR TTO FLAG D[CTY-CONT + 10] ALU[D+1] DEST[IOD] SPEC[IOB-OUT] NORM $ ;ENABLE UART STB MAPF[TTY.WC] CYLEN[IOB-OUT] D[CONST 20] ALU[DORQ] DEST[CTY-STATUS] DEST-A-MEM $ ;SET TTO BUSY D[CTY-CONT + 10] DEST[IOD] SPEC[IOB-OUT] NORM $;CLR UART STB MAPF[TTY.WC] CYLEN[IOB-OUT] D[CONST 7] ALU[D&Q] COND[OBUS=0] JUMP[MAIN] $ ; DONE IF NO PI CHAN D[CTY-CONT + 10] DEST[Q] SHORT $; GET IOB-OUT BITS D[CONST 4] ROT[11] ALU[DORQ] DEST[Q IOD] SPEC[IOB-OUT] NORM $ ;ENABLE XMT INT MAPF[TTY.WC] CYLEN[IOB-OUT] ALU[Q] DEST[CTY-CONT] DEST-A-MEM JUMP[MAIN] $ CTYCO: D[CONST 17] ROT[3] ALU[D&Q] DEST[Q] NORM $;CLR PI BITS D[IR] MASK[7] ALU[DORQ] DEST[CTY-STATUS] DEST-A-MEM JUMP[CTYCO1] NORM $ ;OR IN NEW PI BITS CTYCI: MAPF[TTY.DI] D[IOD] DEST[HOLD] CYLEN[IOB-IN] $;GET UART BITS D[CTY-CONT + 10] DEST[IOD] SPEC[IOB-OUT] NORM $ MAPF[TTY.WC] D[MEM] ROT[26] MASK[1] COND[-OBUS=0] JUMP[CTYCI1] CYLEN[MAX,IOB-OUT,C550] $; J IF RCV RDY CTYCI2: D[CONST 10] ROT[3] ALU[-D&Q] DEST[Q AR] JUMP[CTYCI9] NORM $;CLR TTI BUSY CTYCI1: D[CONST 40] ALU[D&Q] COND[-OBUS=0] JUMP[CTYCI2] C550 $;J IF TTI FLAG ON D[CONST 10] ROT[3] ALU[D#Q] DEST[Q AR] NORM $;COMPL BUSY. D[CONST 10] ROT[3] ALU[D&Q] COND[-OBUS=0] JUMP[CTYCI9] C550 $;J IF BUSY NOW ON D[CONST 40] ALU[DORQ] DEST[Q AR] NORM $; SET TTI FLAG CTYCI9: D[MEM] ROT[25] MASK[1] COND[-OBUS=0] JUMP[CTYCI8] C550 $;J IF XMT RDY D[CONST 20] ALU[DORQ] DEST[CTY-STATUS] DEST-A-MEM POPJ NORM $ ;SET BUSY -- NOTE, NO "AR DEST" IS CORRECT CTYCI8: D[CONST 20] ALU[D&Q] COND[OBUS=0] JUMP[CTYCI3] C550 $; J IF BUSY OFF D[CONST 10] ALU[DORQ] DEST[Q] NORM $; SET FLAG CTYCI3: D[CONST 20] ALU[-D&Q] DEST[CTY-STATUS] DEST-A-MEM POPJ NORM $ ;CLR BUSY CTYCO1: D[IR] ROT[41] MASK[10] DEST[Q] NORM $; GET SET&CLR BITS D[CONST 10] ROT[3] ALU[D&Q] COND[OBUS=0] JUMP[CTYCO4] $ ; J IF CLR TTI FLAG OFF D[CTY-CONT + 10] MASK[11] DEST[Q] NORM $;GET IOB-OUT BITS D[CONST 10] ROT[3] ALU[DORQ] DEST[IOD] SPEC[IOB-OUT] NORM $ ;GET CLR RCV RDY BIT CTYCO3: MAPF[TTY.WC] CYLEN[IOB-OUT] $ ALU[Q] DEST[IOD] SPEC[IOB-OUT] NORM $;CLR IT MAPF[TTY.WC] CYLEN[IOB-OUT] $ CTYCO4: D[CTY-CONT + 10] MASK[11] DEST[Q] NORM $; GET IOB-OUT BITS D[CTY-STATUS + 10] MASK[3] COND[OBUS=0] JUMP[CTYCO5] C550 $ ; J IF NO PI CHAN D[CONST 2] ROT[11] ALU[DORQ] DEST[Q] SHORT $; ENBL RCV INT D[CTY-STATUS + 10] ROT[41] MASK[2] COND[OBUS=0] JUMP[CTYCO5] C550 $ ; J IF NO OUT FLAG OR BUSY D[CONST 4] ROT[11] ALU[DORQ] DEST[Q] SHORT $;ENBL XMT INT CTYCO5: ALU[Q] DEST[IOD] SPEC[IOB-OUT] SHORT $; FIX INT ENBLS MAPF[TTY.WC] CYLEN[IOB-OUT] ALU[Q] DEST[CTY-CONT] DEST-A-MEM JUMP[MAIN] $ ; **** HERE IS DEFN. OF CTY UART CONSTANTS **** CTYRST: D[CONST 4] DEST[DEV-ADR] NORM $ D[CONST 4] ROT[6] DEST[Q CLR-DEV-FROM-INTR] NORM $ D[CONST 74] ALU[DORQ] DEST[Q CTY-CONT] DEST-A-MEM NORM $ D[CONST 3] ROT[6] ALU[DORQ] DEST[IOD] SPEC[IOB-OUT] NORM $; RESET UART MAPF[TTY.WC] CYLEN[IOB-OUT] ALU[0] DEST[CTY-STATUS] DEST-A-MEM $ ALU[Q] DEST[IOD] SPEC[IOB-OUT] NORM JUMP[CTYRS1] $ .USE[AREA356] ;$*$*$*$ Temporary **** CTYRS1: ;Setup entry vectors: IOT vector in left half, interrupt vector in right half MAPF[TTY.WC] C800 D[CONST (CTYDSP / 100)] ROT[18. + 6.] DEST[Q] $ ;High order 6 IOT bits D[CONST (CTYDSP \ 100)] ROT[18.] ALU[DORQ] DEST[Q] NORM $ ;Low order 6 IOT bits D[CONST (CTYINT / 100)] ROT[6.] ALU[DORQ] DEST[Q] NORM $ ;High order 6 interrupt bits D[CONST (CTYINT \ 100)] ROT[0] ALU[DORQ] SPEC[DEST-A-MEM] DEST[CTY-DISP] POPJ NORM $ ;Low order 6 interrupt bits ;Finish setting up vectors and return. ;;; .USE[AREA206] ;;; debuguse = . ;;;:2074 ;%$#@#$% SLOEXP didn't redefine AREA206 properly??? $*$*$*$ .USE[NORMAL] .PAIR CTYCZ: D[AR] ALU[D&Q] COND[-OBUS=0] JUMP[MAIN] C550 $ DOSKIP $ CTYCS: D[AR] ALU[D&Q] COND[OBUS=0] JUMP[MAIN] C550 $ DOSKIP $ ;$*$*$ This code should set up dispatch and interrupt vectors. It will have to ; be moved to the end of regular disk stuff. TVR-Apr80 DSKRST: ALU[0] DEST[IOD] SPEC[IOB-OUT] NORM $ ;SET DSK CTRL COMMAND REGISTER TO 0 (DISABLES INTS). MAPF[4] D[CONST 2] DEST[IOD] SPEC[IOB-OUT] CYLEN[IOB-OUT] $ ;NOW RESET THE CONTROLLER. MAPF[7] ALU[0] DEST[1] DEST-A-MEM CYLEN[IOB-OUT] POPJ $ ;ALSO CLEAR THE PI CHANNEL ASSIGNMENT. SET-DSK-OUT: D[CONST 10] DEST[DEV-ADR] NORM COND[-USER] JUMP[SDSKO2] $ UIOTRP[MUUO] $ ;Watch for IOT-USER mode. SDSKO2: D[MEM] DEST[IOD AR] SPEC[IOB-OUT] NORM POPJ $ ;Kludge to allow disk controller status IOTs from IOT-USER Mode. This is ;so a wizard can look at the state of the disk controller from MDDT (or UEDDT). UDSKST: UIOTRP[MUUO] $ ;Ignore SPEC[IOB-IN] we just did and trap if in user mode. D[IR] ROT[8 + 1 + 1] MASK[10.] DEST[Q] $ ;Extract opcode D[CONST 1] ALU[DORQ] DEST[Q] $ ;Skip first micro instruction that got us here D[CONST 2] ROT[9.] ALU[DORQ] SDISP CYLEN[DISP] SPEC[IOB-IN] $ ;Dispatch again to finish instruction ;$*$*$ This code should set up dispatch and interrupt vectors. It will have to ; be moved to the end of regular disk stuff. TVR-Apr80 TYMRST: ;RESET TYMNET INTERFACE D[CONST 1] DEST[Q] PUSHJ[DEV6CL] NORM $ .REPEAT TYMNET [ JUMP[TYMRS1] NORM $ ;SET INITIAL COROUTINE ADR, INT ENBLS. ];TYMNET .REPEAT 1 - tymnet [ POPJ NORM $ ]; 1 - tymnet ;$*$*$ This code should set up dispatch and interrupt vectors. TVR-Apr80 .REPEAT OTP [ CLKRST: ;RESET 60HZ CLOCK FLAG AND DISABLE ITS INTERRUPTS. D[CONST 1] ALU[NOTD] DEST[Q] PUSHJ[DEV6CL] NORM $ ;LOAD A MASK INTO Q AND GO TO COMMON ROUTINE. ;FALLS IN CLKCLR: ;CLEAR 60HZ CLOCK FLAG. D[CONST 6] DEST[DEV-ADR] SPEC[IOB-OUT] NORM $ MAPF[10] CYLEN[IOB-OUT] ;THIS CLEARS THE FLAG. D[10 + APRSTS] SPEC[A-MEM-APR] ROT[32] MASK[1] DEST[AR] $ ;GET THE APR CONDITIONS WD. D[CONST 1] ALU[NOTD] DEST[Q] JUMP[DEV6ST] NORM $ ;SET OR CLEAR THE HARDWARE INTRPT. ENB. ACCORDING TO ; STATE OF CLK INT ENB BIT IN APR ] ;OTP .REPEAT NTP [ CLKRST: ;Fall in to CLKCLR CLKCLR: START-OUT D[CONST 4] DEST[DEV-ADR] NORM $ ;Clear clk flag. CLKENB: MAPF[7] D[12] SPEC[A-MEM-APR] ROT[26.] DEST[IOD] C600 $ ;Get the APR conditions wd, put CLK INT ENB bit in bit 35. START-OUT NORM $ MAPF[6] C600 POPJ $ ;SET OR CLEAR THE HARDWARE INTRPT. ENB. ACCORDING TO ; STATE OF CLK INT ENB BIT IN APR ] ;NTP .REPEAT OTP [ ;Tape and Timer interact only with old tape ctrl... TAPRST: ;RESET THE TAPE CONTROLLER AND ASSOCIATED DEVICES. D[CONST 7] DEST[DEV-ADR] NORM $ ;SELECT DEVICE. ;; ALU[0] DEST[] DEST-A-MEM NORM $ ;Set tape mode to CORE-DUMP .REPEAT KNYTAPE [ PUSHJ[KNYRST] $ ;Clear KENNEDY formatter, if any. ] D[CONST 1] ROT[35.] DEST[Q] NORM $ ; .REPEAT TIMER [ ;IF INTERVAL TIMER IS PRESENT... D[CONST 1] ROT[35. - 19.] ALU[DORQ] DEST[Q 1] DEST-A-MEM $ ;FORM DATA TO CLR TAPE ERR FF'S, ENABLE TIMER INTRPTS ] ;TIMER .REPEAT 1 - TIMER [ ;IF INTERVAL TIMER IS ABSENT... ALU[Q] DEST[Q 1] DEST-A-MEM $ ;FORM DATA TO CLR TAPE ERR FF'S, DISABLE TIMER INTRPTS ] ;1 - TIMER START-OUT D[CONST 1] ROT[35. - 6] ALU[DORQ] DEST[IOD] NORM $ ;DO SO; ALSO CLEAR TIMER OVERFLOW INTRPT FLAG. MAPF[1] START-OUT D[CONST 1] ROT[35. - 9] DEST[Q IOD] C800 $ ;ALSO CLEAR ALL SIGNALS TO THE DEVICE, SET "CLOCK RUN" MAPF[6] ALU[Q] DEST[2] DEST-A-MEM C800 $ ;RECORD THE "CLOCK RUN" BIT IN A-MEM[2]; EVERYONE WHO ; LOADS THE CTL REG (MAPF[4]) SHOULD INCLUDE IT. D[CONST 60] ROT[35. - 15.] DEST[Q] NORM $ D[CONST 30] ROT[35. - 21.] ALU[DORQ] DEST[Q] NORM $ ;ASSEMBLE -1000. AS 12-BIT NO. ENDING AT BIT 21. START-OUT D[CONST 41] ROT[35. - 7] ALU[DORQ] DEST[IOD] NORM $ ;THIS SETS TIMER CLOCK FOR 100 USEC TICKS, ZEROES COUNTER. MAPF[1] ALU[0] DEST[3] DEST-A-MEM C800 POPJ $ ;INIT THE TIMER REG. TO 0 AND RETURN. ] ;OTP ;$*$*$*$* This should be moved to CFKNYD.SLO TVR-Sep80 .REPEAT NTP [ TAPRST: ;RESET THE TAPE CONTROLLER. D[CONST 7] DEST[DEV-ADR] NORM $ ;SELECT DEVICE. START-OUT ALU[0] DEST[IOD] $ ;Turn off "FORMATTER ENABLE" MAPF[2] LONG $ ;Fall in to TIMRST. TIMRST: D[CONST 5] DEST[DEV-ADR] NORM $ START-OUT D[CONST TIMER] DEST[IOD] NORM $ ;Enable timer interrupts if TIMER is 1, else disable them. MAPF[10] ALU[0] DEST[1] DEST-A-MEM C600 $ ;Clear pi channel ALU[0] DEST[3] DEST-A-MEM NORM POPJ $ ;Clear timer reg. ] ;NTP APRRST: .REPEAT F2SW [ ALU[0] DEST[IOD] SPEC[IOB-OUT] NORM $ ;Clear Addr. Break ];REPEAT F2SW MAPF[1] ALU[0] DEST[APRSTS] SPEC[A-MEM-APR&DEST-A-MEM] CYLEN[IOB-OUT] POPJ $ ;$*$*$ This code should set up dispatch and interrupt vectors. TVR-Apr80 CLRDEVINT: DEST[CLR-DEV-FROM-INTR] POPJ NORM $ ;CLEAR FLAG WHICH CAUSES DEV-ADR TO BE ; ADR OF LAST INTERRUPTING DEVICE, ; SO THE DEV-ADR REGISTER WILL WORK AGAIN. ;------------------------------------------------------------------------------ ; ; PI - Priority Interrupt Service Device 4 ; ;------------------------------------------------------------------------------ ;PI SYSTEM USE OF APR AMEM--- ; 4 MEM PAR ERR(BIT 19), MEM PAR ERR INTRPT ENB(BIT 20), ; PI SYSTEM ON(BIT 28) CHN1-7 ON (BITS 29-35) ; 5 WAITING RQ 1-7 (11-18) IN PROG 1-7 (29-35) ; 6 RQ COUNTS - 4-BIT FIELDS, CHN. 7 AT RIGHT END OF WORD. ; ;Other uses of APR AMEM are documented at the beginning PI-GET-CHN: ;MAKE BINARY CHN. NO. FROM MASK IN AR. D[AR] ROT[34] DEST[AR] NORM $ ;PUT RQ 1 INTO BIT 1 D[CONST 6] DEST[MA] NORM $ ;MA WILL GET 7-CHN (FOR USE IN SHIFTING) PIL1: D[AR] ROT[1] DEST[AR] C550 COND[OBUS<0] JUMP[PIGETMASK] $ ;FOUND FIRST BIT ? D[MA] ALU[D-1] DEST[MA] NORM JUMP[PIL1] $ ;NO. DECREMENT COUNT AND LOOP. PIGETMASK: D[MA] DEST[ROTR] NORM $ ;LOAD ROTATE AMT. D[CONST 1] ROT[R] DEST[AR] NORM POPJ $ ;MAKE MASK OF FIRST BIT ONLY IN AR. PI-CHECK-RQS: ;SEE IF IT IS TIME TO TAKE AN INTRPT. .REPEAT STANSW [ ;Determine which PI channels should be enabled for PAN D[14] SPEC[A-MEM-APR] ROT[35. - 10.] DEST[Q] PUSHJ[PANIST] NORM $ ;Select only those channels turned on and readyt to interrupt MAPF[PAN-INT-ENB] CYLEN[IOB-OUT] D[15] SPEC[A-MEM-APR] ROT[18.] MASK[7] DEST[AR] COND[OBUS=0] JUMP[MAIN] $ ;ANY RQ'S ? ];.REPEAT STANSW .REPEAT 1 - STANSW [ D[15] SPEC[A-MEM-APR] ROT[18.] MASK[7] DEST[AR] C550 COND[OBUS=0] JUMP[MAIN] $ ;ANY RQ'S ? ];.REPEAT 1 -STANSW ALU[0] DEST[DEV-ADR] NORM PUSHJ[PI-GET-CHN] $ ;GET UNARY CHN NO. IN AR, SHIFT AMT. IN MA, ROTR D[14] ROT[34] C550 COND[-OBUS<0] JUMP[MAIN] $ ;EXIT IF PI SYS NOT ON. D[MASK 7] ROT[R] DEST[Q] NORM $ ;MASK OF CHN AND ALL HIGHER CHNS. D[15] ALU[D&Q] C550 COND[-OBUS=0] JUMP[MAIN] $ ;EXIT IF THIS OR HIGHER CHN IN PROGRESS. D[AR] DEST[Q] NORM $ ;MOVE UNARY CHN # TO Q. D[14] ALU[D&Q] C550 COND[OBUS=0] JUMP[MAIN] $ ;EXIT IF CHN NOT ON. D[MA] ROT[2] DEST[ROTR] NORM $ ;GET SHIFT AMT 4 TIMES LARGER, TO ACCESS CNT FIELD D[CONST 1] ROT[R] DEST[Q] NORM $ ;A ONE ALIGNED WITH RQ CNT FIELD FOR THIS CHN. D[16] ALU[D-Q] DEST[Q HOLD] NORM $ ;DECREMENT OUR WAITING RQ COUNT. D[16] ALU[D#Q] DEST[Q] NORM $ ;DID WE OVERFLOW ? D[CONST 20] ROT[R] ALU[D&Q] COND[-OBUS=0] C550 JUMP[.] $ ;LOOP HERE FOREVER IF WE OVERFLOWED 4-BIT CNT FIELD D[MEM] DEST[6 Q] DEST-A-MEM NORM $ ;PUT BACK WORD OF RQ COUNTS. D[CONST 17] ROT[R] ALU[D&Q] C550 COND[-OBUS=0] JUMP[PIINTGO] $ ;JUMP IF OUR COUNT NEQ 0 D[AR] ROT[18.] ALU[NOTD] DEST[Q] NORM JUMP[PIL11] $ ;MASK FOR CLEARING THE WAITING RQ BIT. PIINTGO: D[CONST 0] ALU[NOTD] DEST[Q] NORM $ ;DON'T CLEAR THE BIT, RQ'S STILL WAITING PIL11: D[15] ALU[D&Q] DEST[Q] NORM $ ;GET STATUS B, EITHER DO OR DO NOT CLEAR RQ BIT D[AR] ALU[DORQ] DEST[5] DEST-A-MEM NORM $ ;SET IN PROGRESS BIT, STORE STATUS B. D[PC] DEST[Q AR] NORM $ ;GET PC INTO Q, AR. D[MASK 43] ROT[37] ALU[D&Q] DEST[CRYOV] NORM $ ;CLR USR MODE ;;; D[MA] ROT[18.] ALU[DORQ] DEST[1] DEST-A-MEM NORM $ ;;; This is an obsolete bug trap -- DWP 9/80 ;; FOLLOWING INSTR. IS DEBUGGING AID D[CONST 56] DEST[Q] NORM $ ;PREPARE TO CALC. INTRPT. ADDRESS. D[MA] ROT[1] ALU[Q-D] DEST[MA] NORM JUMP[PIMUUO] $ ;FETCH INTRPT. INSTR AND GO INTERPRET IT. PIGEN: ;ENTER WITH CHN IN AR TO REQUEST INTRPT. ALU[0] DEST[DEV-ADR] NORM PUSHJ[CLRDEVINT] $ D[14] DEST[Q] NORM $ D[CONST 1] ROT[18.] ALU[D+Q] DEST[4] DEST-A-MEM NORM $ D[CONST 7] DEST[Q] NORM $ ;7-CHN IS AMT TO SHIFT BY FOR MASK BIT. D[AR] MASK[3] ALU[Q-D] DEST[MA] NORM PUSHJ[PIGETMASK] $ ;LOAD ROTR, FORM MASK IN AR PIGEN1: D[14] ROT[34] C550 COND[-OBUS<0] JUMP[PIGENWT] $ ;BRANCH IF PI SYS NOT ON. MASK[7] D[2] ROT[R] DEST[Q] NORM $ ;MASK OF CHN AND ALL HIGHER CHNS. D[15] ALU[D&Q] C550 COND[-OBUS=0] JUMP[PIGENWT] $ ;BRANCH IF THIS OR HIGHER CHN IN PROGRESS. D[AR] DEST[Q] NORM $ ;MOVE UNARY CHN # TO Q. D[14] ALU[D&Q] C550 COND[-OBUS=0] JUMP[PIINTGO] $ ;IF CHN ON, GO TAKE INTRPT. PIGENWT: ;INTRPT CANNOT HAPPEN NOW, SO SET A WAITING RQ. D[MA] ROT[2] DEST[ROTR] NORM $ ;GET SHIFT AMT 4 TIMES LARGER, TO GET CNT FIELD D[CONST 1] ROT[R] DEST[Q] NORM $ ;A ONE ALIGNED WITH RQ CNT FIELD FOR THIS CHN. D[16] ALU[D+Q] DEST[Q HOLD] NORM $ ;INCREMENT OUR WAITING RQ COUNT. D[CONST 10] ROT[R] ALU[D&Q] COND[-OBUS=0] C550 JUMP[. + 2] $ ;DON'T LET COUNT GET HIGHER THAN 7. D[MEM] DEST[6] DEST-A-MEM NORM $ ;PUT BACK WORD OF RQ COUNTS. D[15] DEST[Q] NORM $ ;GET STATUS B. D[AR] ROT[18.] ALU[DORQ] DEST[5] DEST-A-MEM NORM JUMP[MAIN] $ ;SET WAITING RQ BIT. PI-DISMISS: D[15] SPEC[A-MEM-APR] MASK[7] DEST[AR] C550 COND[-OBUS=0] PUSHJ[PI-GET-CHN] $ D[15] SPEC[A-MEM-APR] DEST[Q] NORM $ D[AR] ALU[-D&Q] DEST[5] SPEC[A-MEM-APR&DEST-A-MEM] NORM JUMP[PI-CHECK-RQS] $ PICONO: ;Here from any CONO PI, D[MA] MASK[7] DEST[AR] NORM $ ALU[0] DEST[DEV-ADR] NORM $ D[14] DEST[Q] NORM $ ;GET STATUS A D[MA] ROT[21.] C550 COND[-OBUS<0] JUMP[PIL7] $ D[CONST 1] ROT[35. - 20.] ALU[DORQ] DEST[Q] NORM $ ; TURN ON PAR ERR INTRPT ENB. PIL7: D[MA] ROT[20.] C550 COND[-OBUS<0] JUMP[PIL8] $ D[CONST 1] ROT[35. - 20.] ALU[-D&Q] DEST[Q] NORM $ ;TURN OFF PAR ERR INT ENB PIL8: D[MA] ROT[19.] C550 COND[-OBUS<0] JUMP[PIL9] $ D[CONST 1] ROT[35. - 19.] ALU[-D&Q] DEST[Q] NORM $ ;CLEAR MEM PAR ERR FLAG PIL9: D[MA] ROT[5] C550 COND[OBUS18] PUSHJ[PI-RESET] $ D[MA] ROT[12] C550 COND[-OBUS18] JUMP[PIL3] $ D[CONST 1] ROT[7] ALU[DORQ] DEST[Q] NORM $ ; PI ON PIL3: D[MA] ROT[11] C550 COND[-OBUS18] JUMP[PIL4] $ D[CONST 1] ROT[7] ALU[-D&Q] DEST[Q] NORM $ ; PI OFF PIL4: D[MA] ROT[7] C550 COND[-OBUS18] JUMP[PIL5] $ D[AR] ALU[DORQ] DEST[Q] NORM $ ; CHNS ON PIL5: D[MA] ROT[10] C550 COND[-OBUS18] JUMP[PIL6] $ D[AR] ALU[-D&Q] DEST[Q] NORM $ ; CHNS OFF PIL6: ALU[Q] DEST[4] DEST-A-MEM NORM $ D[MA] ROT[6] C550 COND[-OBUS18] JUMP[PI-CHECK-RQS] $ D[AR] MASK[7] ALU[0-D] DEST[Q] NORM $ ;GENERATED INTRPTS REQUESTED. CHECK TO ; MAKE SURE ONLY ONE CHN IS SPECIFIED. D[AR] MASK[7] ALU[D&Q] DEST[Q] NORM $ D[AR] MASK[7] ALU[D-Q] C600 COND[-OBUS=0] JUMP[.] $ ;HANG HERE IF MORE THAN ONE. D[AR] MASK[7] DEST[AR] NORM PUSHJ[PI-GET-CHN] $ ;GET BINARY CHN. NUMBER AND UNARY MASK. NORM JUMP[PIGEN1] $ ;GO GENERATE REQUEST. PICONISUB: D[14] SPEC[A-MEM-APR] MASK[18.] DEST[Q] NORM $ ;GET SYS ON AND CHN ON BITS. D[15] SPEC[A-MEM-APR] MASK[10] DEST[AR] NORM $ ;GET PI IN PROG BITS D[AR] ROT[10] ALU[DORQ] DEST[AR Q] NORM $ D[15] SPEC[A-MEM-APR] ROT[18.] MASK[10] DEST[AR] NORM $ ;GET WAITING RQ BITS, AND RETURN IN LEFT HALF. D[AR] ROT[18.] ALU[DORQ] DEST[AR Q] NORM POPJ $ PI-RESET: ALU[0] DEST[4] SPEC[A-MEM-APR&DEST-A-MEM] NORM $ ALU[0] DEST[5] SPEC[A-MEM-APR&DEST-A-MEM] NORM $ ALU[0] DEST[6 Q] SPEC[A-MEM-APR&DEST-A-MEM] NORM POPJ $ ;;; ALU[0] DEST[1] SPEC[A-MEM-APR&DEST-A-MEM] NORM POPJ $ ;;; This is an obsolete bug trap -- DWP 9/80 END-OF-PI-CODE: ;; MBOOT MOVED TO PAGE WITH REST OF TAPE STUFF ;MAPIOT MAPIO1 MAPCO0 MAPCOB MAPCOC MFT1 MFT1A MFT1D MFRD MFOTH MBLT3 SETHLF QORCRY SETHFU BWRTA1 MBLT2 MAPCWT MAPCW1 MAPCW2 ;------------------------------------------------------------------------------ ; ; BBN Pager - Map CONO Dispatch Table ; ;*** What these things do should documented here. It's hard enough to find it ;*** elsewhere! TVR-Apr80 ; ; This code is all BBN dependent. It will be replaced for other pagers. ; ;------------------------------------------------------------------------------ .ORG[5200] ;$*$*$ This should be fixed JUMP[MAPCO0] NORM $ ;CONO 0 DEST[CLR-MAP] JUMP[MAPCO1] NORM $ ;CONO 1 -- START MAP CLEARING UAOP1 $ ;CONO 2 -- Ill. Instruction DEST[CLR-MAP] JUMP[MAPCO1] NORM $ ;CONO 3 -- START MAP CLR D[CONST 1] DEST[DEV-ADR] JUMP[MAPCO4] NORM $; CONO 4 D[CONST 1] DEST[DEV-ADR] JUMP[MAPCO4] NORM $; CONO 5 JUMP[MAPCO6] NORM $ ;CONO 6 DEST[CLR-MAP] JUMP[MAPCO7] NORM $ ;CONO 7 .USE[AREA51] ;$*$*$ This is truely silly. The CTY code appears ; after the map dispatch and the map code ; after the CTY dispatch! .PAIR UIOTRP[MUUO] $ MAPIOT: D[IR] ROT[9.] COND[-OBUS<0] JUMP[MAIN] C550 $ ;NOP IF DEV. 20 D[CONST 14] ALU[D#Q] COND[OBUS=0] JUMP[MAPIO1] C550 $; IS IT CONO ? D[CONST 13] ALU[D#Q] COND[OBUS=0] JUMP[MAPDO] C550 $; NO IS IT DATAO? ILGIOT $ ;ELSE ILLEGAL MAPIO1: D[IR] MASK[3] DEST[Q] NORM $ D[CONST 52] ROT[6] ALU[DORQ] SDISP C600 $ MAPCO0: D[CONST 1] DEST[DEV-ADR] PUSHJ[MAPCOA] NORM $ D[12] DEST[Q] NORM $ ; GET SIGN BIT = ENBL FOR EXEC 0-77777 ALU[0] DEST[DEV-ADR] SHORT $ D[IR] MASK[2] DEST[IOD] SPEC[IOB-OUT] SHORT $ MAPF[10] CYLEN[IOB-OUT] DEST[CLR-MAP] D[CONST 20] LLOAD $ ; TURN OFF MAPPING & START CLEARING MAP LOOP [.] C550 $ ;WAIT FOR MAP CLR TO FINISH -- OTHERWISE THE ; READS OF 71 AND 72 BELOW DON'T HAPPEN (ON F2 #1). .REPEAT 1 - WAITS [ ;Now add 1 to abs. loc. 31 of main mem (for statistics keeping) ;;;; D[CONST 32] DEST[MA] NORM PUSHJ[MPINC1] $ ];.REPEAT 1 - WAITS D[CONST 71] DEST[MA] SHORT $; FETCH MAGIC LOC D[CONST 1] DEST[DEV-ADR] CYLEN[FIXM] $; WAIT FOR DATA D[MEM] MASK[13] DEST[AR] SHORT $ D[AR] ROT[11] DEST-A-MEM DEST[4] NORM $; MBR D[MEM] ROT[18.] MASK[13] DEST[AR] SHORT $ D[AR] ROT[11] DEST-A-MEM DEST[1] NORM $; UBR .REPEAT 1 - WAITS [ D[MEM] ROT[27] MASK[5] DEST[AR] SHORT $ D[AR] ROT[4] DEST-A-MEM DEST[3] NORM $; AC BASE REG ];.REPEAT 1 - WAITS D[MEM] ROT[7] MASK[3] ALU[0-D] DEST[AR] COND[OBUS=0] JUMP[MAPCOB] C600 $; ADDRS LIMIT, J IF 0 D[AR] MASK[3] DEST[AR] SHORT $ D[AR] ROT[16] DEST[AR] JUMP[MAPCOC] NORM $ ; FORM SMALLEST ILLEGAL ADDRESS MAPCOB: D[CONST 20] ROT[16] DEST[AR] SHORT $ MAPCOC: D[CONST 1] ROT[43] ALU[D&Q] DEST[Q] SHORT $ ; GET SIGN BIT = ENBL FOR EXEC 0-77777 D[AR] ALU[DORQ] DEST-A-MEM DEST[AR 2] NORM $; ADDRS LIMIT .REPEAT WAITS [ D[11] DEST[HI-ABS-MA MA] SHORT $ ;Fetch first location of user page table D[MEM] MASK[13] DEST[3] DEST-A-MEM LONG $ ;Wait for memory to finish, then save page table entry. ];.REPEAT WAITS D[CONST 72] DEST[MA] SHORT $; GET NEXT WORD D[MEM] DEST[Q] LONG $ ;LONG to wait for data to arrive. D[CONST 1] ROT[32] ALU[-D&Q] DEST-A-MEM DEST[5] JUMP[MAPCOE] NORM $ ; AGE & PROCESS BITS ;------------------------------------------------------------------------------ ; ; MAP FAULT DISPATCHES COME HERE (6100 + MAPF*4 ) ; ; MAP traps happen on next micro instruction after a MEMSTO or STRT-WRT. ; They also happen after micro instruction containing a DEST[FIXMAC...], ; as in FIXM1 for example. The trap happens by forcing an unconditional ; jump to an address determined by MAP-DISP register and the MAPF of ; field of the failing micro instruction. Otherwise, that micro ; instruction is executed normally. ; ; This code should be the same for all kinds of maps. However, it will ; be necessary to define symbolically the trap code, i.e. the thing that ; is usually being loaded left half of Q. After doing that, and updating ; necessary state of PC and flags, the code leave by jumping to MFT1B, ; the map dependent page fault/page fill code, with fault code in Q and ; failing address in the MA. ; ; *** As you will notice, there are NO spare trap codes. If you need one, ; *** talk to me about a scheme for fixing this and improving page fault ; *** recovery. TVR-Apr80 ; ;------------------------------------------------------------------------------ .ORG[6100] ;Fixed by hardware to xx100 JUMP[.] $ ;ILLEGAL MAP FAULT -- MICROCODE BUG IF YOU GET HERE .REPEAT XUCODE [ :16100 ;copy for high mem JUMP[6100] $ ];XUCODE ;**** Consider looking at STOP switch in the future. TVR - Mar80 ; ;To find out non-destructively how you lost, start at 2003 (on an F2) ;you will be stopped at PC+1, assuming you lose trying to display ;that instruction in the lights (i.e. (PC) not mapped in) ; ;You can get here by examining/depositing a location in the ;hardware map (i.e. it may only be asking for a page-fill cycle). : 6104 ;EXECUTE (&INDIRECT) FAULTS HERE MFT1: D[CONST 2] ROT[18.] DEST[Q] NORM $; CODE FOR EXECUTE MFT1A: D[CONST 1] DEST[DEV-ADR] NORM $ MFT1D: DEST[CLR-DEV-FROM-INTR] SPEC[IOB-IN] SHORT $ D[IOD] MASK[3] DEST[AR IR-ADR] JUMP[MFT1B] MAPF[4] CYLEN[IOB-IN] $ : 6110 ;NORMAL READ FAULT MFRD: D[CONST 10] ROT[18.] DEST[Q] NORM $;CODE FOR RD MFOTH: D[PC] ALU[D-1] DEST[PC] JUMP[MFT1A] NORM $ .REPEAT XUCODE [ :16110 ;NORMAL READ FAULT -High mem duplicate instr. D[CONST 10] ROT[18.] DEST[Q] NORM $;CODE FOR RD ];XUCODE : 6114 ;RMW HERE, DECREMENTS PC D[CONST 14] ROT[18.] DEST[Q] JUMP[MFOTH] NORM $ .REPEAT XUCODE [ :16114 ;RMW -High mem duplicate instr. D[CONST 14] ROT[18.] DEST[Q] JUMP[MFOTH] NORM $ ];XUCODE : 6120 ;WRITES (NORMAL) HERE (NO DECREMENT PC) D[CONST 4] ROT[18.] DEST[Q CLR-DEV-FROM-INTR] NORM $ D[CONST 1] DEST[DEV-ADR] NORM $ D[AR] DEST-A-MEM DEST[7] NORM $;SAVE STORE DATA D[IR] MASK[18.] DEST[MA] NORM JUMP[MFT1D] $; RESTORE MA .REPEAT XUCODE * VID [ : 16124 ; 5-- BLT-RD IN HIGH MEM (DPY-RD) ;;; JUMP[DPYRD] NORM $ ];XUCODE * VID : 6124 ; 5-- BLT-RD D[PC] MASK[18.] ACSEL[AC] DEST[O_AC PC] NORM $; RESTORE PC & DEST ADR D[CONST 10] ROT[18.] DEST[Q] SHORT $; CODE FOR RD MBLT3: D[AR] ROT[18.] SPEC[LEFT] ALU[DORAC] ACSEL[AC] DEST[AC] JUMP[MFOTH] NORM $; GET SRC ADR .REPEAT XUCODE * VID [ : 16130 ; 6-- BLT-WRT IN HIGH MEM (DPY-WRT) ;;; JUMP[DPYWRT] NORM $ ];XUCODE * VID : 6130 ;6-- BLT-WRT D[PC] MASK[18.] ACSEL[AC] DEST[O_AC PC MA] SPEC[MA_PC] NORM $; RESTORE PC, GET DEST ADR ALU[Q-1] DEST[AR] NORM $; ADJUST SRC ADR D[CONST 4] ROT[18.] DEST[Q] JUMP[MBLT3] NORM $; CODE FOR WRT : 6134 ;7-- BLT-RDA ACSEL[AC] D[AR] DEST[AC] NORM $; NEW DEST ADR D[CONST 10] ROT[18.] DEST[Q] JUMP[MFOTH] NORM $; CODE FOR RD : 6140 ; 10-- BLT-WRTA D[CONST 4] ROT[18.] DEST[Q CLR-DEV-FROM-INTR] NORM $; CODE FOR WRT D[MA] MASK[18.] DEST[Q] PUSHJ[BWRTA1] NORM $; GET MA, SAVE STORE DAT D[AR] MASK[18.] ALU[D#Q] COND[OBUS=0] JUMP[MBLT2] C550 $ ALU[Q-1] DEST[Q MA] JUMP[MBLT2] NORM $; CORRECT MA : 6144 ;11-- BYTE-ILD PUSHJ[SETHLF] NORM $; SET HALF JUMP[6110] NORM $; NORMAL READ ;Page fault in the middle of a interruptable instruction. Set HALF (BIS) ;flag as part of page fault processing so that instruction gets restarts in ;the proper way. SETHLF: D[CONST 2] ROT[36] DEST[Q] COND[USER] JUMP[SETHFU] NORM $;BIT 4--HALF ;Get ready to set HALF (BIS) flag. ;Watch for special case of User page fault from Exec. TVR-May80 QORCRY: D[PC] ALU[DORQ] DEST[CRYOV] POPJ NORM $;SET HALF : 6150 ;12 -- BYTE-IDP PUSHJ[SETHLF] NORM $; SET HALF JUMP[6114] NORM $;NORMAL RMW ;When a DEST[CRYOV] is done, the EXEC shift register is cleared (set) to ;whatever the user bit in the new CRYOV is. This destroys the information ;about which space a page fault came from on XCTR (XCT mapped) instruction. ;We turn it on explicitly here. Note that since a user cannot do a XCTR, ;we only have to worry about the case of being in EXEC mode and getting a ;user mode page fault. TVR-May80 SETHFU: D[PC] ALU[DORQ] DEST[CRYOV] NORM $ ;Set the half flag. ;Don't return yet, we need to reset EXEC-SR SET-TEMP-USER POPJ $ ;Remember that the page fault was from a user page!! : 6154 ;13 -- BYTE-IND PUSHJ[SETHLF] NORM $; SET HALF JUMP[6104] NORM $; NORMAL INDIRECT : 6160 ;BLT-WRTB -- XCT MAPPED BLT STORES D[CONST 4] ROT[18.] DEST[Q CLR-DEV-FROM-INTR] NORM $; CODE FOR WRT D[MA] MASK[18.] DEST[Q] PUSHJ[BWRTA1] NORM $; GET MA, SAVE STORE DAT D[CONST 4] ROT[18.] DEST[Q] NORM $ D[AR] ACSEL[AC] DEST[AC] JUMP[MFOTH] NORM $; RESTORE AC : 6164 ;-- MAPFTR -- TRAP WHIILE FETCHING JSYS TARGET D[CONST 50] ROT[18.] DEST[Q CLR-DEV-FROM-INTR] NORM $; PI CODE D[CONST 1] DEST[DEV-ADR] NORM $ D[AR] DEST-A-MEM DEST[7] JUMP[MFOTH] NORM $ : 6170 ;PPOP-- 16 -- POP & POPJ FETCH- RE-INCR PDL PNTR -- THEN LIKE READ FAULT D[CONST 1,,1] ACSEL[AC] ALU[D+AC] DEST[AC] JUMP[MFRD] NORM $ : 16174 ;UPPER MEM COPY OF 6174 D[CONST 4] ROT[18.] DEST[Q CLR-DEV-FROM-INTR] NORM $ : 6174 ;17-- WRITES WITH RELEVANT ADRS IN MA (NO DECR PC) D[CONST 4] ROT[18.] DEST[Q CLR-DEV-FROM-INTR] NORM $ D[CONST 1] DEST[DEV-ADR] SHORT $ D[MEM] DEST-A-MEM DEST[7] JUMP[MFT1D] NORM $;SAVE STORE DATA BWRTA1: D[CONST 1] DEST[DEV-ADR] NORM $ D[MEM] DEST-A-MEM DEST[7] POPJ NORM $ MBLT2: D[AR] MASK[18.] ALU[Q-D] DEST[Q] SHORT $; COUNT HOW MANY WORDS MOVED D[AR] ROT[18.] ALU[Q+D] DEST[AR] SHORT $;FORM NEW SRC ACSEL[AC] D[MA] MASK[18.] DEST[AC] SHORT $;NEW DEST D[CONST 4] ROT[18.] DEST[Q] NORM $ D[AR] ACSEL[AC] ROT[18.] SPEC[LEFT] ALU[DORAC] DEST[AC] JUMP[MFOTH] NORM $; OR IN NEW SRC OTHER = . ;$*$*$ This is the end of the fix areas, In'Sh'Allah TVR-Apr80 : 5340 ;$*$*$ The APR dispatch ends at 5340. ;*$*$* Fudge area accounting AREA53 = . .USE[AREA53] MAPCWT: ALU[Q] LLOAD NORM $ LOOP[.] CYLEN[LONG] $; WAIT FOR MAP TO CLEAR D[CONST 4] DEST[IOD] SPEC[IOB-OUT] SHORT $;TURN ON MAP MAPF[10] D[AR] COND[OBUS<0] JUMP[MAPCW9] CYLEN[MAX,IOB-OUT,C550] $ ; JUMP IF WHOLE MAP ON (INCLUDING EXEC 0-77777)- DONE MAPCW1: D[CONST 77] MAPF[10] LLOAD NORM $ MAPCW2: D[PC] DEST[AR] SHORT $;SAVE FLAGS ALU[0] DEST[MA CRYOV] SHORT $;INIT MA, SET EXEC D[CONST 10] ROT[6] DEST[Q] SHORT $ .REPEAT NEWMAP [ D[CONST 1] DEST[DEV-ADR] NORM $ ; -- FOR WRITING MAP SPEC[IOB-OUT] SHORT $ ;SET FIRST PART OF ; EXEC MAP TO POINT TO "NULL MAP" LOCS(UNMAPPED) MAPF[2] D[MA] MASK[18.] C800 $ ;MAP DATA COMES FROM OBUS. D[MA] ALU[D+Q] DEST[MA] LOOP[. - 2] NORM $;LOOP ] ; NEWMAP .REPEAT 1 - NEWMAP [ D[MA] MASK[18.] DEST[STO-MAP] NORM $ ;SET FIRST PART OF EXEC MAP TO POINT TO "NULL MAP" LOCS(UNMAPPED) D[MA] ALU[D+Q] DEST[MA] LOOP[. - 1] NORM $;LOOP ] ; 1 - NEWMAP D[IR] MASK[3] DEST[IOD] SPEC[IOB-OUT] SHORT $; RESTORE MAP D[AR] DEST[CRYOV] JUMP[MAIN] MAPF[10] CYLEN[IOB-OUT] $; RESTORE FLAGS, DONE ;------------------------------------------------------------------------------ ; End map trap code which is common to all maps. ;------------------------------------------------------------------------------ ;MAPCOA MAPCOE MAPCO1 MAPCOG MAPCO4 MPOFF1 MAPOFF MAPCO6 MAPCO7 MAPCW9 MAPDO MFUS MFA3 MFA7 MFA6 MFA4 MFT1B MFHIEX MFA1 MFA2 MFB3 MFTYP1 MFTYP0 ;------------------------------------------------------------------------------ ; BBN MAP CONO, continued ; ; This code will need to be rewritten for another kind of map. ; ;------------------------------------------------------------------------------ MAPCOA: DEST[CLR-DEV-FROM-INTR] SPEC[IOB-IN] SHORT $ D[IOD] MASK[3] DEST[IR-ADR] MAPF[4] POPJ CYLEN[IOB-IN] $ ;GET MAP, ECC & OV ENBL BITS MAPCOE: ALU[0] DEST[DEV-ADR] SHORT $ D[IR] MASK[3] DEST[IOD] SPEC[IOB-OUT] NORM $ ; RESTORE MAP STATE MAPF[10] D[CONST 1] DEST[Q] JUMP[MAPCWT] CYLEN[IOB-OUT] $ MAPCO1: D[CONST 1] DEST[DEV-ADR] PUSHJ[MAPCOA] NORM $ ;GET ENABLE BITS IN IR D[12] DEST[AR] NORM $ ; GET SIGN BIT = ENBL EXEC 0-77777 .REPEAT NEWMAP [ .REPEAT 1 - WAITS [ ;Now add 1 to abs. loc. 32 of main mem (for statistics keeping) ;;;; ALU[-1] DEST[MAP-DISABLE] NORM $ ;;;; D[CONST 32] DEST[MA] NORM PUSHJ[MPINC1] $ ];.REPEAT 1 - WAITS ] ;NEWMAP ALU[0] DEST[DEV-ADR] SHORT $ D[CONST 5] DEST[Q] JUMP[MAPCWT] NORM $ MAPCOG: D[CONST 1] DEST[DEV-ADR] NORM $ D[12] MASK[43] DEST[Q] NORM $ D[IR] MASK[1] DEST[AR] SHORT $ ;GET LOW BIT OF CONO D[AR] ROT[43] ALU[DORQ] DEST-A-MEM DEST[2] NORM $ ;GET SIGN BIT = EXEC 0-77777 MAP ENBL SPEC[IOB-IN] SHORT $ MAPF[4] D[IOD] MASK[3] DEST[Q] CYLEN[IOB-IN] $ ALU[0] DEST[DEV-ADR] SHORT $ D[CONST 4] ALU[DORQ] DEST[IOD] SPEC[IOB-OUT] SHORT $ D[CONST 4] ALU[DORQ] DEST[IR-ADR] MAPF[10] POPJ CYLEN[IOB-OUT] $ ;TURN ON MAP MAPCO4: DEST[CLR-DEV-FROM-INTR] SPEC[IOB-IN] NORM PUSHJ[MAPOFF] $ MPOFF1: MAPF[10] CYLEN[IOB-OUT] JUMP[MAIN] $ ; DONE MAPOFF: D[IOD] MASK[3] DEST[IR-ADR] MAPF[4] CYLEN[IOB-IN] $ ALU[0] DEST[DEV-ADR] SHORT $ D[IR] MASK[2] DEST[IOD] SPEC[IOB-OUT] NORM POPJ $ MAPCO6: DEST[CLR-DEV-FROM-INTR] PUSHJ[MAPCOG] NORM $ JUMP[MAPCW1] NORM $ MAPCO7: DEST[CLR-DEV-FROM-INTR] PUSHJ[MAPCOG] CYLEN[LONG] $ CYLEN[LONG] $; WAIT FOR MAP TO CLEAR CYLEN[LONG] $ MAPCW9: ALU[0] LLOAD NORM $; SET UP ONLY PAGE 0 JUMP[MAPCW2] NORM $ ;------------------------------------------------------------------------------ ;DATAO CLEARS THE "ASSOCIATIVE" REGISTER MAPPING THE ADDRESS OF THE DATAO ; THIS REPLACES CONO 2. ;------------------------------------------------------------------------------ MAPDO: D[CONST 1] DEST[DEV-ADR] PUSHJ[MAPCOA] NORM $;GET MAP BITS .REPEAT 1 - NEWMAP [ ALU[0] DEST[DEV-ADR] NORM $ ] D[CONST 4] DEST[IOD] SPEC[IOB-OUT] SHORT $;TURN ON MAP MAPF[10] CYLEN[IOB-OUT] $ .REPEAT NEWMAP [ SPEC[IOB-OUT] SHORT $ ;REQUEST MAP WRITE CYCLE. MAPF[2] D[CONST 1] ROT[32] C800 $ ] .REPEAT 1 - NEWMAP [ D[CONST 1] ROT[32] DEST[STO-MAP] NORM $ ] ;CLR MAP ENTRY ASSOCIATED WITH MA D[IR] MASK[3] DEST[IOD] SPEC[IOB-OUT] C800 $; RESTORE ENABLES MAPF[10] CYLEN[IOB-OUT] JUMP[MAIN] $ ;------------------------------------------------------------------------------ ; ; BBN MAP - Handle map trap and page fill cycles. ; ; This code will need to be rewritten for another kind of map. ; ;------------------------------------------------------------------------------ MFUS: D[12] MASK[40] DEST[Q] NORM $;GET LIMIT REG D[MA] ALU[D-Q] COND[-OBUS<0] JUMP[MTRPAL] C600 $;J IF MA PAST ADDRS LIMIT D[11] DEST[Q] JUMP[MFA1] NORM $;GET USER BASE REG. MFA3: D[MEM] ROT[12] MASK[1] COND[-OBUS=0] JUMP[MFA4] C550 $ ;J IF MODIF. BIT ON MFA7: D[AR] DEST[IR-ALL] SHORT $; SAVE ORRIGINAL MA D[AR] DEST-A-MEM DEST[6] NORM $; SAVE TRAP WORD D[CONST 1] ROT[27] ALU[DORQ] DEST[AR] SHORT $; TURN ON WRT-PREVENT, SAVE NEW MAP WORD MFA6: D[MEM] MASK[33] DEST[Q] JUMP[MFA5] NORM $; GET CST ENTRY, GO DO MFA4: D[IR] ROT[26] MASK[1] COND[OBUS=0] JUMP[MFA7] C550 $; J IF NO WRT-PERMIT D[AR] DEST[IR-ALL] SHORT $; SAVE ORRIGINAL MA D[AR] DEST-A-MEM DEST[6] NORM $; SAVE TRAP WORD D[MASK 43] ROT[30] ALU[D&Q] DEST[AR] JUMP[MFA6] NORM $; CLEAR WRT-PREVENT ;------------------------------------------------------------------------------ ; Enter here with fault code in Q and address in MA to handle page fault or ; page fill cycle. MAP-EXEC-SR (i.e. USER condition) is still undisturbed. ;------------------------------------------------------------------------------ MFT1B: D[MA] MASK[18.] ALU[DORQ] DEST[AR] COND[USER] JUMP[MFUS] NORM $;GET FAILED ADDRS, J IF USER D[MA] ROT[24] MASK[2] DEST[Q] NORM $; HIGH ORDER 2 BITS D[CONST 3] ALU[D-Q] COND[OBUS=0] JUMP[MFHIEX] C600 $; J IF PRIVATELY MAPPED PART D[CONST 30] ROT[6] DEST[Q] JUMP[MFA1] NORM $; PAGE TAB @ 3000 MFHIEX: D[14] DEST[Q] NORM $ MFA1: ALU[0] DEST[DEV-ADR] NORM $ D[IR] MASK[2] DEST[IOD] SPEC[IOB-OUT] NORM $ ;CLEAR MAPPING D[IR] MASK[3] DEST-A-MEM DEST[APRENB] MAPF[10] CYLEN[IOB-OUT] $ ;SAVE AR, ECC INT D[MA] ROT[33] MASK[11] ALU[D+Q] DEST[MA HI-ABS-MA] NORM $; FETCH PAGE TABLE ENTRY D[CONST 16] ROT[14] DEST[IR-ADR] NORM $; PREPARE INITIAL PERMIT BITS D[CONST 1] DEST[DEV-ADR] NORM $ MFA2: D[CONST 3] DEST[Q] CYLEN[FIXM] $; DON'T CLEAR IND PNTR. COUNT, WAIT FOR FETCH D[MEM] ROT[18.] ALU[DORQ] DEST[Q] CYLEN[FIXM+1] $;GET PERMIT BITS D[IR] ALU[D&Q] DEST[IR-ADR] SHORT $; AND THEM IN D[MEM] ROT[13] MASK[3] COND[-OBUS=0] JUMP[MFTR1] C550 $; CHECK FOR TRAP BITS MFB3: D[MEM] ROT[15] MASK[1] COND[OBUS=0] JUMP[MFTR2] C550 $; J IF NO ACCESS PERMIT D[MEM] ROT[2] MASK[2] DEST[Q] COND[OBUS=0] JUMP[MFTYP0] C550 $; GET TYPE CODE, J IF 0 ALU[Q-1] DEST[Q] COND[OBUS=0] JUMP[MFTYP1] C550 $; J IF 1 ALU[Q-1] DEST[Q] COND[-OBUS=0] JUMP[MFTR3] C550 $; J IF NOT 2 D[IR] ROT[43] MASK[1] COND[-OBUS=0] JUMP[MFTR41] C550 $; TYPE 2, J IF >2 INDR. PNTRS D[IR] ALU[D+1] DEST[IR-ADR] SHORT $; COUNT IND. PNTRS D[MEM] ROT[33] MASK[15] DEST[Q] SHORT $; GET PAGE TABLE # D[MEM] DEST-A-MEM DEST[6] NORM $; SAVE PNTR D[CONST 2] ROT[14] ALU[D+Q] DEST[MA HI-ABS-MA] NORM $; FETCH PAGE TABLE PNTR D[16] MASK[11] DEST[Q] CYLEN[FIXM] $; GET PAGE #, WAIT FOR MEM D[MEM] ROT[18.] MASK[4] COND[-OBUS=0] JUMP[MFTR4] C550 $; PAGE OUT-OF-CORE? D[MEM] MASK[13] DEST[HOLD] NORM $ D[MEM] ROT[11] ALU[DORQ] DEST[MA HI-ABS-MA] JUMP[MFA2] NORM $; LOOP MFTYP1: D[MEM] ROT[33] MASK[15] DEST[Q] SHORT $; GET SHARED PAGE # D[CONST 2] ROT[14] ALU[D+Q] DEST[MA HI-ABS-MA] NORM $; FETCH SHARED PNTR MFTYP0: D[CONST 12] ROT[14] DEST[Q] CYLEN[FIXM] $; GET R-X MASK D[IR] ALU[D&Q] COND[OBUS=0] JUMP[. + 2] C600 $; J IF NEITHER R NOR X D[IR] ALU[DORQ] DEST[IR-ADR] NORM $; TURN ON R AND X D[IR] ROT[27] MASK[3] ALU[NOTD] DEST[Q] CYLEN[FIXM] $; GET RWX ENBL BITS, INVERTED D[MEM] ROT[18.] MASK[4] COND[-OBUS=0] JUMP[MFTR5] CYLEN [C550] $; J IF OUT-OF-CORE D[AR] ROT[21] MASK[3] ALU[D&Q] DEST[Q] COND[-OBUS=0] JUMP[MFTR6] C550 $; J IF ILLEGAL ACCESS TYPE (RWX) ;MFA5 JSMFR MFTR1 MFTR10 MFB5 MFB4 MFC1 MFTR2 MTRPAL MFTR3 MFTR4 MFTR5 MFTR6 MFTR7 MFTR9 MFTR41 MAPRST MAPRSS MAPRSL D[MEM] MASK[13] DEST[Q] SHORT $; GET ABS PAGE # D[CONST 40] ROT[6] ALU[DORQ] DEST[MA HI-ABS-MA] SHORT $; GET CORE STATUS ENTRY D[IR] ROT[12] ALU[NOTD] DEST[Q] CYLEN[FIXM] $; GET RWX DISABLES D[CONST 24] ROT[25] ALU[D&Q] DEST[Q] SHORT $; GET ONLY R & X D[CONST 4] ROT[25] ALU[D+Q] DEST[Q] SHORT $; MOVE X BIT LEFT 1 D[MA] ROT[11] MASK[24] ALU[DORQ] DEST[Q] SHORT $; OR IN PAGE ADDRS D[MEM] ROT[3] MASK[3] COND[OBUS=0] JUMP[MFTR7] C550 $; J IF CST AGE SAYS TRAP D[AR] ROT[20] MASK[1] COND[OBUS=0] JUMP[MFA3] C550 $;J IF NO WRT RQ D[AR] DEST[IR-ADR] SHORT $; SAVE ORRIGINAL MA D[AR] DEST-A-MEM DEST[6] NORM $; SAVE TRAP WORD D[MASK 43] ROT[30] ALU[D&Q] DEST[AR] SHORT $; TURN OFF WRT PREVENT, SAVE NEW MAP WORD D[CONST 1] ROT[32] DEST[Q] SHORT $; GET MODIFICATION BIT D[MEM] MASK[32] ALU[DORQ] DEST[Q] SHORT $; OR INTO CST WORD MFA5: D[15] ALU[DORQ] DEST[HOLD] NORM $;OR IN AGE, ETC D[MA] DEST[Q] SHORT $; SAVE CST ADDRS D[IR] MASK[18.] DEST[MA HI-ABS-MA] NORM $; GET ORIGINAL MA .REPEAT NEWMAP [ D[CONST 1] DEST[DEV-ADR] SHORT $ ;NOW TURN MAP ON. D[CONST 4] DEST[IOD] SPEC[IOB-OUT] SHORT $ MAPF[10] SPEC[IOB-OUT] CYLEN[IOB-OUT] $ MAPF[2] D[AR] C800$; LOAD MAP NOP $ ;%%%%%%% FOR DEBUGGING $$$$$$$$ ] ; NEWMAP .REPEAT 1 - NEWMAP [ ALU[0] DEST[DEV-ADR] SHORT $ ;NOW TURN MAP ON. D[CONST 4] DEST[IOD] SPEC[IOB-OUT] SHORT $ MAPF[10] CYLEN[IOB-OUT] $ D[AR] DEST[STO-MAP] NORM $; LOAD MAP ] ; 1-NEWMAP ALU[0] DEST[IOD] SPEC[IOB-OUT] C800 $ ;MAP OFF MAPF[10] CYLEN[IOB-OUT] COND[-USER] JUMP[. + 2] $ D[CONST 17] ROT[11] DEST[MAP-EXEC-SR] NORM $ ALU[Q] DEST[MA STRT-WRT] NORM $; STORE CST .REPEAT 1 - WAITS [ ;Now add 1 to abs. loc. 30 of main mem (for statistics keeping) ;;;; D[CONST 30] DEST[MA] NORM PUSHJ[MPINC1] $ ];.REPEAT 1 - WAITS D[CONST 1] DEST[DEV-ADR] NORM $ D[16] DEST[AR] NORM $ ALU[0] DEST[DEV-ADR] NORM $ D[10 + APRENB] DEST[IOD] SPEC[IOB-OUT] NORM $; TURN MAP BACK ON, ETC. MAPF[10] CYLEN[MAX,IOB-OUT,C550] D[AR] ROT[15] MASK[1] COND[-OBUS=0] JUMP[JSMFR] $ ; DO SPECIAL JSYS STUFF IF APPROPRIATE D[AR] ROT[20] MASK[1] COND[OBUS=0] JUMP[MAIN] C550 $; DONE IF NO WRT D[AR] ROT[17] MASK[1] COND[-OBUS=0] JUMP[MAIN] C550 $; DONE IF READ D[AR] MASK[18.] DEST[MA] SHORT $;GET ORRIG. MA D[CONST 1] DEST[DEV-ADR] SHORT $ D[17] DEST[MEMSTO] JUMP[MSMAIN1] NORM $; STORE THE STORE DATA, & PROCEDE MPINC1: NORM $ ;Wait for mem fetch to finish. D[MEM] ALU[D+1] DEST[MEMSTO] NORM $ ;Add one to data and store back in same mem loc. .REPEAT NEWMAP [ ALU[0] DEST[MAP-DISABLE] NORM POPJ $ ] .REPEAT 1 - NEWMAP [ NORM POPJ $ ] JSMFR: D[AR] MASK[18.] DEST[MA] NORM $ D[CONST 1] DEST[DEV-ADR] NORM $ D[17] DEST[AR] JUMP[MUJSM1] NORM $; RESTORE STORE DATA MFTR1: D[MEM] ROT[11] MASK[1] COND[-OBUS=0] JUMP[MFTR9] C550 $; J IF TRAP TO USER D[MEM] ROT[12] MASK[1] COND[-OBUS=0] JUMP[MFTR10] C550 $;J IF WRT TRAP D[MEM] JUMP[MFTR2] NORM $; TREAT BOTH "TRAP-TO-MON" CODES AS IMMEDIATE MFTR10: D[AR] ROT[20] MASK[1] COND[OBUS=0] JUMP[MFB3] C550 $; WRT RQ? J IF NO D[CONST 44] ROT[36] DEST[Q] SHORT $; GET ERROR CODE BITS -- WRT TRAP MFB5: MFB4: D[AR] ALU[DORQ] DEST[AR Q] COND[USER] JUMP[. + 2] NORM $; OR ERROR BITS IN, J IF USER MODE D[CONST 1] ROT[18.] ALU[DORQ] DEST[AR] NORM $; TURN ON EXEC BIT D[CONST 5] ROT[6] DEST[Q] SHORT $ D[CONST 71] ALU[DORQ] DEST[Q] SHORT $; FORM 571 D[14] ALU[DORQ] DEST[MA HI-ABS-MA] SHORT $; ADD PSB (MON BASE TAB) D[AR] DEST[MEMSTO] CYLEN[FIXM] $; STORE ERROR BITS THERE D[AR] ROT[20] MASK[1] COND[OBUS=0] JUMP[MFC1] C550 $; J IF NO WRT RQ D[AR] ROT[17] MASK[1] COND[-OBUS=0] JUMP[MFC1] C550 $; J IF RD RQ D[MA] ALU[D+1] DEST[MA] SHORT $; GO TO 572 D[17] DEST[MEMSTO] NORM $; SAVE STORE DATA MFC1: ALU[0] DEST[DEV-ADR] CYLEN[MEMSTO] $ ALU[0] DEST[IOD] SPEC[IOB-OUT] NORM $; TURN OFF MAP MAPF[10] ALU[0] DEST[HI-ABS-MA] CYLEN[IOB-OUT] $ D[CONST 70] DEST[MA] SHORT $; FETCH TRAP INSTR ALU[0] DEST[DEV-ADR] CYLEN[FIXM] $ D[10 + APRENB] DEST[IOD] SPEC[IOB-OUT] SHORT $; TURN ON MAP D[PC] DEST[Q AR] MAPF[10] CYLEN[IOB-OUT] $ D[MASK 43] ROT[37] ALU[D&Q] DEST[CRYOV] NORM $;CLR USER D[CONST 55] ROT[2] DEST[Q] JUMP[MUUO44] NORM $ MFTR2: D[CONST 41] ROT[36] DEST[Q] JUMP[MFB5] NORM $; ASCCESS PERMISSION TRAP MTRPAL: MFTR3: D[CONST 40] ROT[36] DEST[Q] SHORT $ D[CONST 1] ROT[33] ALU[DORQ] DEST[Q] JUMP[MFB5] NORM $; ILLEGAL PT ENTRY TYPE, ADDRESS LIMIT MFTR4: ;ALL THESE ARE NOT-IN-CORE MFTR5: D[CONST 22] ROT[36] DEST[Q] JUMP[MFB5] NORM $; NOT-IN-CORE MFTR6: D[CONST 5] ALU[D&Q] COND[OBUS=0] JUMP[. + 3] C550 $; J IF NO R OR X ERROR D[CONST 4] ROT[33] ALU[DORQ] DEST[Q] SHORT $; OR IN "R OR X ERROR" BIT D[CONST 2] ALU[D&Q] COND[OBUS=0] JUMP[. + 2] C550 $; J IF NO W ERROR D[CONST 2] ROT[33] ALU[DORQ] DEST[Q] SHORT $; OR IN W ERROR BIT D[CONST 7] ALU[-D&Q] DEST[Q] SHORT $ D[CONST 40] ROT[36] ALU[DORQ] DEST[Q] JUMP[MFB4] NORM $; GROUP 2 MFTR7: D[CONST 10] ROT[36] DEST[Q] JUMP[MFB4] NORM $; AGE ERR -- GROUP 0 MFTR9: D[CONST 42] ROT[36] DEST[Q] JUMP[MFB4] NORM $; USER TRAP MFTR41: D[CONST 20] ROT[36] DEST[Q] NORM $; GROUP 1 D[CONST 1] ROT[33] ALU[DORQ] DEST[Q] JUMP[MFB4] NORM $; TOO MANY INDR. PNTRS ;------------------------------------------------------------------------------ ;Reset map. Clear entire map to zero. This is because even though the map ;will stop stores from happening, fetches still happen irregardless of state ;of map and if map points at non-existent memory (on for example, an immediate ;mode instruction), the machine will get a spurious ECC interrupt. ; ;It is assumed that the device address is set to 1 when this thing is called. ;------------------------------------------------------------------------------ MAPRST: SET-TEMP-EXEC $ ;Begin at the beginning of EXEC space. D[CONST 1] ROT[9.] DEST[Q] SHORT $ ;Increment for MA MAPRSS: D[CONST 1] ROT[18.] ALU[D-Q] DEST[MA] NORM $ ;Start at the top and work down. MAPRSL: .REPEAT 1 - NEWMAP [ D[CONST 1] ROT[35. - 9.] DEST[STO-MAP] NORM $ ;Set mapping to zero, Invalid D[MA] ALU[D-Q] DEST[MA] COND[-MA-AC] JUMP[. - 1] C550 $ ;Repeat for each page in this space. ];.REPEAT 1 - NEWMAP .REPEAT NEWMAP [ START-OUT SHORT $ MAPF[2] D[CONST 1] ROT[35. - 9.] NORM $ ;Set mapping to zero, Invalid D[MA] ALU[D-Q] DEST[MA] COND[-MA-AC] JUMP[. - 2] C800 $ ;Repeat for each page in this space ];.REPEAT NEWMAP SET-TEMP-USER COND[-USER] JUMP[MAPRSS] $ ;Repeat once more if currently doing EXEC space. This ;time for USER space. We can do this because EXEC-SR is ;latched at the end of the cycle. ALU[0] DEST[DEV-ADR] NORM $ D[CONST 1] DEST[IOD] SPEC[IOB-OUT] NORM $ MAPF[14] CYLEN[IOB-OUT] D[CONST 3] DEST[MAP-DISP] $ DEST[CLR-MI-ERR] POPJ $ ;Done ;JSYS1 JSYS2 UMOVX XCT1 XCTUMV XCT5 XCT4 XCT6 XCT3 XCT13 XCT18 XCT12 XCT11 XDISP XCT2 XFIXMA XCTAC XCTSTK XCTS1 XCTS2 XCT10 XCTBLG XCTBYT XBY1 XBY4 XBY15 XBY14 XBY13 XBY3 ;------------------------------------------------------------------------------ ; ; BBN added instructions. Sometimes used by other than TENEX ; ;------------------------------------------------------------------------------ JSYS1: FIXM1 $ D[PC] DEST[AR] NORM $ ;SAVE PC & FLAGS D[MEM] MASK[18.] DEST[PC] NORM $; JUMP TO RIGHT HALF D[MEM] ROT[18.] MASK[18.] DEST[MA] SHORT $ D[AR] DEST[MEMSTO] MEMSTMA $ JSYS2: C550 D[CONST 1] ROT[36] ALU[D&Q] COND[OBUS=0] JUMP[. + 2] $; J IF EXEC MODE ALU[0] DEST[MAP-EXEC-SR] NORM $; TEMP TURN OFF USER D[CONST 10] ROT[6] DEST[Q] SHORT $ D[MA] ALU[DORQ] DEST[MA] SHORT $; FETCH POINTER WORD FIXM1 $ D[MEM] MASK[18.] DEST[PC] NORM $; J TO RIGHT HALF D[PC] DEST[Q] SHORT $ D[AR] ROT[5] C550 COND[OBUS<0] JUMP[. + 2] $ ;If we came from exec mode, then we... D[CONST 1] ROT[34] ALU[DORQ] DEST[Q] SHORT $ ; ...TURN ON FLAG BIT 7 D[CONST 1] ROT[36] ALU[-D&Q] DEST[CRYOV] SHORT $; TURN OFF USER D[MEM] ROT[18.] MASK[18.] DEST[MA] SHORT $; LEFT HALF D[AR] DEST[MEMSTO] MEMSTMA $; STORE PC .DEFINE JCFM [JAD] [ D[PC] ROT[10] MASK[1] COND[-OBUS=0] JUMP[JAD] C550 $;J IF CALL FM MON] UMOVX: COND[USER] JUMP[MUUO] NORM $ D[MEM] DEST[Q] NORM $ D[CONST 1] ROT[41] ALU[D+Q] DEST[HOLD] NORM $ D[CONST 5] DEST[Q] JUMP[XCTUMV] NORM $ ;------------------------------------------------------------------------------ ; ; XCTR - Execute Relocated ; ; If in Exec mode and the AC field of the XCT instruction is non-zero, ; it means do some of the references from User mode if PC bit (?), ; meaning JSYS from Moniter, is not set. ; ; This code is not map dependent, although other maps (like ITS) may code ; the bits in the AC field differently, requiring some rewriting. ; ; Warning: This code is complex and prone to bugs. Many probably lurk ; in the cracks. If you find one, please document it even if ; no solution seems to appear. ;------------------------------------------------------------------------------ XCT1: D[PC] ALU[D-1] DEST[PC] NORM $ COND[USER] JUMP[XCT2] NORM $ D[IR] ROT[15] MASK[4] DEST[Q] SHORT $; SAVE XCT AC FLD XCTUMV: D[MEM] DEST[AR IR-ALL MA] COND[-MEM-IDX-IND] JUMP[XCT3] NORM $ XCT5: D[IR] ROT[18.] MASK[4] COND[OBUS=0] JUMP[XCT4] C550 MAPF[2] $; J IF NO IDX FLD D[IR] MASK[18.] ALU[IX+D] DEST[MA IR-ADR AR] $; DO INDEX XCT4: D[IR] ROT[16] MASK[1] COND[OBUS=0] JUMP[XCT3] C550 MAPF[2] $; J IF NO INDR D[CONST 10] ALU[D&Q] COND[-OBUS=0] PUSHJ[XFIXMA] C550 $; PUSHJ IF ADDR CALC USER XCT6: ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[NORM-IND] CYLEN[FIXM] $ ;;; FIXM1 $ ;;; ;It was overdecrementing PC TVR-Mar80 SET-TEMP-EXEC $ D[MEM] DEST[AR IR-23 MA] COND[MEM-IDX-IND] JUMP[XCT5] NORM $ XCT3: ALU[Q] DEST[IR-ADR] SHORT MAPF[2] $; SAVE XCT AC FLD D[IR] ROT[7] MASK[7] DEST[Q] SHORT $; GET HO 7 BITS OF OPCODE D[CONST 54] ALU[D#Q] COND[OBUS=0] JUMP[XCTSTK] C550 $; J IF STACK GROUP D[CONST 27] ALU[D#Q] COND[OBUS=0] JUMP[XCTBYT] C550 $; J IF BYTE GROUP D[CONST 52] ALU[D#Q] COND[OBUS=0] JUMP[XCTBLG] C550 $; J IF GROUP WITH BLT IN IT XCT13: D[IR] MASK[4] DEST[Q] SHORT $; GET XCT AC FLD XCT18: D[CONST 5] ALU[D&Q] COND[OBUS=0] JUMP[XDISP] C550 $; J IF NEITHER RELEVANT BIT COND[MA-AC] JUMP[XCT10] NORM $; J IF EF ADR IS AC JCFM[XDISP] ;J IF CALL FM MON D[CONST 1] ALU[D&Q] COND[OBUS=0] JUMP[XCT11] C550 $;J IF BIT OFF D[CONST 4] ALU[D&Q] COND[OBUS=0] JUMP[XCT12] C550 $; J IF OTHER BIT OFF D[CONST 03] ROT[11] DEST[MAP-EXEC-SR] JUMP[XDISP] NORM $; SET SRC & DEST TO USER XCT12: D[CONST 02] ROT[11] DEST[MAP-EXEC-SR] JUMP[XDISP] NORM $; SET DEST TO USER XCT11: D[CONST 01] ROT[11] DEST[MAP-EXEC-SR] NORM $; SET SRC TO USER XDISP: D[MA] DEST[MA IR-ADR] DISP[2000] SPEC[PC+1-IF] CYLEN[DISP] $ ;This is the dispatch for normal non-relocated XCT XCT2: D[MEM] DEST[IR-ALL AR MA] DISP[2174] SPEC[PC+1-IF] CYLEN[DISP] $ ;Call here after setting MA if this memory cycle is supposed to ;be relocated to the previous address space. ;This must preserve Q and AR, some callers depend on it. XFIXMA: COND[MA-AC] JUMP[XCTAC] NORM $; J IF ADDRS IS AC D[PC] ROT[10] MASK[1] COND[-OBUS=0] POPJ C550 MAPF[2] $; LEAVE IF CALL FM MON SET-TEMP-USER $ D[MA] DEST[MA] POPJ NORM $ ;MA is reference to AC of previous address space. XCTAC: .REPEAT 1 - WAITS [ ACSEL[AC] ALU[AC] DEST[HOLD] SHORT $; SAVE AC ACSEL[AC] DEST[CLR-DEV-FROM-INTR AC] D[MA] SHORT $; GET AC ADDRS D[CONST 1] DEST[DEV-ADR] SHORT $ ACSEL[AC] D[13] ALU[D+AC] DEST[AC] SHORT $; ADD IN AC BASE REG. ACSEL[AC] D[CONST 75] ROT[11] ALU[D+AC] DEST[AC] SHORT $ ACSEL[AC] D[CONST 7] ROT[17] ALU[D+AC] DEST[AC] NORM $ D[MEM] ACSEL[AC] DEST[O_AC MA] POPJ NORM $ ];.REPEAT 1 - WAITS .REPEAT WAITS [ D[PC] ROT[10] MASK[1] COND[-OBUS=0] POPJ C550 MAPF[2] $; LEAVE IF CALL FM MON ACSEL[AC] D[MA] DEST[O_AC HOLD] $ ;Get address of AC, we need to mung it ;Save AC, we can't use Q for some reason [???] ACSEL[AC] D[CONST 77] ROT[9. + 3.] ALU[D+AC] DEST[AC] NORM $ ;Add page number of window ;Use 770xxx for window into user ACs D[MEM] ACSEL[AC] DEST[O_AC MA CLR-DEV-FROM-INTR] NORM $ ;Restore AC and set MA from AC to start read .REPEAT 1 - NEWMAP [ D[CONST 1] DEST[DEV-ADR] NORM $ ;Select appropriate A-MEM D[13] ROT[9.] MASK[36. - 13.] DEST[STO-MAP] COND[OBUS=0] JUMP[.] NORM $ ;Extract address and position for map ;Not R,W,X excluded. Not NO ENTRY AT ALL ;Hang if attempt to reference user ACs with no shadow ;memory defined at time of CONO PAG, ];.REPEAT 1 - NEWMAP .REPEAT NEWMAP [ D[CONST 1] DEST[DEV-ADR] SPEC[IOB-OUT] NORM $ ;Select appropriate A-MEM ;Set place in map to write it and start map write MAPF[2] ROT[9.] MASK[36. - 13.] COND[OBUS=0] JUMP[.] NORM $ ;Finish map write. ;Not R,W,X excluded. Not NOT ENTRY AT ALL ;Hang if attempt to reference user ACs with no shadow ;memory defined at time of CONO PAG, ];.REPEAT NEWMAP D[MA] DEST[MA] POPJ NORM $ ];.REPEAT WAITS XCTSTK: ;;; COND[-MA-AC] JUMP[XCT13] NORM $; J IF EF ADR NOT AC (TREAT NORMALLY) D[IR] ROT[11] MASK[2] DEST[Q] COND[OBUS=0] JUMP[XCT13] C550 $; GET 2 LOW ORDER BITS OF OP CODE, J IF PUSHJ D[CONST 3] ALU[D#Q] COND[OBUS=0] JUMP[XCT13] C550 $; J IF POPJ .repeat 0[ D[CONST 2] ALU[D#Q] COND[OBUS=0] JUMP[XCTS1] C550 $; J IF POP D[CONST 4] DEST[Q] JUMP[XCTS2] NORM $ XCTS1: D[CONST 1] DEST[Q] SHORT $ XCTS2: D[IR] ALU[D&Q] COND[OBUS=0] JUMP[XCT13] C550 $; J IF AC REF NOT USER D[IR] ALU[D-Q] DEST[IR-ADR] PUSHJ[XCTAC] NORM $; FIX EF ADR. MAPF[2] JUMP[XCT13] NORM $ ];.repeat 0 D[CONST 2] ALU[D#Q] COND[OBUS=0] JUMP[XPOP1] C550 $; J IF POP JUMP[XPUSH1] NORM $ ;Someday, move code over here (when we have space) XCT10: PUSHJ[XCTAC] NORM $; FIX EF ADR MAPF[2] D[MA] MASK[4] DEST[IR-ADR] DISP[2000] SPEC[PC+1-IF] CYLEN[DISP] $ XCTBLG: D[IR] ROT[11] MASK[2] DEST[Q] COND[OBUS=0] JUMP[XCT13] C550 $; GET 2 LO BITS OF OPCODE, J IF EXCH D[CONST 1] ALU[D#Q] COND[OBUS=0] JUMP[XCTBLT] C550 $; J IF BLT D[IR] MASK[4] DEST[Q] JUMP[XCT18] NORM $; GET XCT AC FLD, PROCEDE ;XCTR of byte instruction. AC field bits: ; 4 - byte pointer in previous address space ; 2 - byte pointer address calculation in previous address space ; 1 - byte in previous address space XCTBYT: D[IR] ROT[42] MASK[1] SPEC[PC+1] COND[-OBUS=0] PUSHJ[XFIXMA] C550 $; PUSHJ IF B.P. FETCH IS NOT EXEC XBY1: D[IR] ROT[11] MASK[1] COND[OBUS=0] JUMP[XBY3] C550 MAPF[2] $;J IF BP WILL BE INCR FIXM1 $ D[MEM] DEST[AR Q] NORM $; GET BP XBY4: SET-TEMP-EXEC $ D[AR] MASK[18.] DEST[MA] COND[-MEM-IDX-IND] JUMP[XBY13] NORM $; J IF BP HAS NO IDX OR INDR XBY15: D[AR] ROT[18.] MASK[4] DEST[AC-SEL] COND[OBUS=0] JUMP[XBY14] C550 MAPF[2] $; J IF NO IX FLD D[IR] ROT[43] MASK[1] COND[OBUS=0] JUMP[XBY16] C550 $;J IF BP ADR CALC NOT USER D[AR] ROT[18.] MASK[4] DEST[MA] PUSHJ[XCTAC] NORM $;FETCH IDX REG FIXM1 $ D[MASK 4] ROT[18.] ALU[-D&Q] DEST[Q] NORM $;CLEAR INDEX FIELD OF Q D[MEM] MASK[18.] ALU[D+Q] DEST[Q AR MA] JUMP[XBY14] NORM $ ;Above instruction makes the indexed byte pointer, with ;garbage in bits 14-17 that doesn't hurt anything. ;There will be no carry into PPSS. XBY16: D[MASK 18.] ROT[18.] ALU[D&Q] DEST[Q] NORM $ ;HLLZS BP IN Q D[AR] MASK[18.] ACSEL[REG] ALU[D+AC] DEST[AR] SHORT $ D[AR] MASK[18.] ALU[DORQ] DEST[Q AR MA] SHORT $ XBY14: D[AR] ROT[16] MASK[1] COND[OBUS=0] JUMP[XBY13] C550 MAPF[2] $; J IF NO INDR D[IR] ROT[43] MASK[1] COND[-OBUS=0] PUSHJ[XFIXMA] C550 $; PUSHJ IF BP ADR CALC IS USER FIXM1 $ SET-TEMP-EXEC $ D[AR] ROT[14] MASK[14] DEST[AR] SHORT $ D[AR] ROT[30] DEST[Q] SHORT $ D[MEM] MASK[27] ALU[DORQ] DEST[Q AR MA] COND[MEM-IDX-IND] JUMP[XBY15] NORM $ XBY13: D[IR] MASK[1] COND[-OBUS=0] PUSHJ[XFIXMA] MAPF[2] $; MAKE MA OK D[IR] ROT[10] MASK[1] COND[OBUS=0] JUMP[LDB5] C550 MAPF[2] $; DISTINGUISH LOADS FROM DEPOSITS, J IF LOAD JUMP[DPB5] NORM $ XBY3: FIXM2 $ D[MEM] DEST[AR Q] COND[HALF] JUMP[XBY4] NORM $;GET BP, J IF NO INCR D[AR] ROT[14] MASK[6] DEST[AR MASKR] COND[BYTE-OVF] PUSHJ[IBT1] NORM $; GET S FLD, HANDLE OVERFLOW D[AR] ROT[36] ALU[Q-D] DEST[Q AR MEMSTO] COND[-MA-AC] JUMP[. + 2] NORM $; SUB S FROM P ACSEL[MA] D[MEM] DEST[AC] NORM $ PUSHJ[SETHLF] NORM $; SET HALF JUMP[XBY4] NORM $; (IN CASE OF MAP FAULTS) ;XCTBLT XBLTL XPUSH1 XPDLO2 XPOP1 XPOP2 XPOP3 ;;;;;.USE[OTHER] DWP 9-19-80 XCTBLT: D[MA] SPEC[PC+1] DEST[O_AC AR] NORM $; END ADR IN AC, AC IN AR XBLTL: D[AR] ROT[18.] MASK[18.] DEST[MA] SHORT $; GET WORD D[IR] ROT[42] MASK[1] COND[-OBUS=0] PUSHJ[XFIXMA] C550 $; FIX IF USER ADDRS ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[BLT-RDA] CYLEN[FIXM] $ D[MEM] DEST[Q] SHORT $; GET DATA WORD D[AR] MASK[18.] DEST[MA] SHORT $; GET DEST ADR D[IR] MASK[1] DEST[MAP-EXEC-SR] COND[-OBUS=0] PUSHJ[XFIXMA] C550 $;FIX MA ADDRS ALU[Q] DEST[MEMSTO] SHORT $ D[AR] MASK[18.] ALU[D-AC] MAPF[BLT-WRTB] COND[-OBUS<0] JUMP[BLTA12] C600 $ D[CONST 1,,1] DEST[Q MAP-EXEC-SR] COND[-MA-AC] JUMP[. + 2] NORM $ D[MEM] ACSEL[MA] DEST[AC] SHORT $ D[AR] ALU[D+Q] DEST[AR] JUMP[XBLTL] NORM $; TEST FOR INTERPT HERE ? ***** ;Special case for PUSH. Check for AC reference from stack pointer XPUSH1: D[IR] MASK[1] COND[OBUS=0] JUMP[XCT13] C550 $ ;If not mapping stack references, it's simple D[IR] ROT[36. - 2] MASK[1] COND[-OBUS=0] PUSHJ[XFIXMA] SPEC[PC+1] C550$ ;Make sure we're referring to the right place here. ;Also, we're now executing the instruction (PC+1) FIXM1 $ ;Check page faults for effective address part. D[MEM] DEST[AR] NORM $ ;Copy away the thing that we want to push D[CONST 1,,1] ALU[D+AC] DEST[AC MA] COND[CRY0] JUMP[XPDLO2] C550 $ ;Advance frame pointer and check for overflow PUSHJ[XFIXMA] NORM $ ;Decide whether to map destination. D[AR] DEST[MEMSTO] MEMST $ ;Finish instruction. We're done XPDLO2: PUSHJ[XFIXMA] NORM $ ;Fixup AC references JUMP[PDLO2] NORM $ ;Done. Take stack overflow trap ;Special case for POP. Check for AC reference from stack pointer XPOP1: D[IR] ROT[11] DEST[Q] NORM SPEC[PC+1] $ ;Save bit meaning 'source from user' in format that can ;be fed easily to EXEC-SR ;Now we're executing the PUSH (implied by PC+1) D[MA] DEST[IR-ADR] NORM $ ;Restore normal effective address ACSEL[AC] D[CONST 1,,1] ALU[AC-D] DEST[MA O_AC] NORM $ ;Update AC and MA for stack reference D[CONST 4] ROT[11] ALU[D&Q] COND[-OBUS=0] PUSHJ[XFIXMA] C550 $ ;Fixup stack addressing if user AC ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[PPOP] CYLEN[FIXM] $ ;Check for page faults D[MEM] DEST[AR] NORM $ ;Find somewhere safer for thing to push D[CONST 1] ROT[11] ALU[D&Q] DEST[MAP-EXEC-SR] COND[OBUS=0] JUMP[XPOP3] C550 $ ;Set appropriate mode to do store in D[IR] MASK[22] DEST[MA] NORM $ ;Extract address and fetch it from the appropriate page. COND[MA-AC] PUSHJ[XCTAC] NORM $ ;Fixup AC addressing if needed. (We can't combine this and ;previous instruction because MA is strobed at end of cycle. ;We can't call XFIXMA because it uses SET-TEMP-USER which ;would affect the next instruction fetch. Sigh...) XPOP2: D[CONST 1,,1] ALU[D+AC] COND[CRY0] JUMP[PDLO5] C550 $ ;Try for overflow again. Take it if you need it. D[AR] DEST[MEMSTO] MEMST $ ;Write out thing we POP'ped XPOP3: D[IR] MASK[22] DEST[MA] NORM JUMP[XPOP2] $ ;Extract address and don't do anything special about it ;APRDSP PIDSP AREA53 APRCO APRCO2 APRCO3 APRIEN APRC1 APRC2 APRCHK APRCK1 APDINT APRCI APRCII APRDI APIOT ;------------------------------------------------------------------------------ ; ; APR and PI instructions ; ;------------------------------------------------------------------------------ .ORG[5300] ;APR & PI IOT DISP TABLE APRDSP: ILGIOT $; BLKI APR NOP $ ALU[0] DEST[DEV-ADR] NORM $; DATAI -- RD SW DEST[CLR-DEV-FROM-INTR] SPEC[IOB-IN] JUMP[APRDI] NORM $ ILGIOT $ ;BLKO APR NOP $ JUMP[MAIN] $; DATAO NOP $ D[IR] MASK[13] DEST[Q] NORM $; GET CONO BITS D[CONST 33] ROT[5] ALU[-D&Q] DEST[Q] JUMP[APRCO] NORM $ PUSHJ[APRCI] NORM $; CONI -- GET BITS IN AR & Q D[AR] MASK[18.] DEST[MEMSTO] MEMST $ PUSHJ[APRCI] NORM $; CONSZ -- GET BITS IN AR & Q D[IR] MASK[18.] DEST[Q] JUMP[CTYCZ] NORM $ PUSHJ[APRCI] NORM $; CONSO -- GET BITS IN AR & Q D[IR] MASK[18.] DEST[Q] JUMP[CTYCS] NORM $ PIDSP: .REPEAT 3[ ILGIOT $ NOP $ ] ;DATAO PI -- Set lights D[CONST 0] DEST[DEV-ADR] PUSHJ[SETLTS] NORM $ ;Just like examine...? JUMP[MAIN] SHORT $ JUMP[PICONO] NORM $; PI CONO NOP $ PUSHJ[PICONISUB] NORM $; CONI -- GET BITS IN AR & Q D[AR] DEST[MEMSTO] MEMST $ PUSHJ[PICONISUB] NORM $; CONSZ -- GET BITS IN AR & Q D[IR] MASK[18.] DEST[Q] JUMP[CTYCZ] NORM $ PUSHJ[PICONISUB] NORM $; CONSO -- GET BITS IN AR & Q D[IR] MASK[18.] DEST[Q] JUMP[CTYCS] NORM $ .USE[NORMAL] APRCO: D[CONST 1] ROT[3] ALU[-D&Q] DEST[AR] SHORT $ D[IR] ROT[43] MASK[21] ALU[NOTD] DEST[Q] SHORT $ ; GET CLR BITS D[CONST 7] ALU[-D&Q] DEST[Q] SHORT $ ; Remove PI assignment D[10 + APRSTS] SPEC[A-MEM-APR] ALU[D&Q] DEST[Q CLR-DEV-FROM-INTR] SHORT $ ; CLEAR INDICATED BITS D[AR] ALU[DORQ] SPEC[A-MEM-APR&DEST-A-MEM] DEST[APRSTS AR] NORM $ ; SET INDICATED BITS & CHAN D[IR] ROT[41] MASK[1] COND[OBUS=0] JUMP[APRCO2] C550 $ ; J IF NO CLR OVERFLOW BIT D[PC] MASK[43] DEST[CRYOV] SHORT $; CLR OV ; Remove overflow bit from current PC flags APRCO2: D[IR] ROT[36] MASK[1] COND[OBUS=0] JUMP[APRCO3] C550 $ ; J IF NO CLR FLT OV D[MASK 43] ROT[41] DEST[Q] SHORT $ ; Remove bit from current PC flags D[PC] ALU[D&Q] DEST[CRYOV] SHORT $ ; CLR FLT OV APRCO3: D[IR] ROT[33] MASK[1] COND[-OBUS=0] PUSHJ[CLKCLR] C550 $ ; CLR CLOCK FLAG IF INDICATED ; --- ; TEMP **** APRCI: APRIEN: PUSHJ[APRCII] DEST[CLR-DEV-FROM-INTR] NORM $ ; GET APR CONI BITS D[CONST 1] DEST[DEV-ADR] SPEC[IOB-IN] NORM $ ; Select and read MAP and ECC enablings D[IOD] MAPF[4] MASK[3] DEST[Q] CYLEN[IOB-IN] $ ALU[0] DEST[DEV-ADR] SHORT $ ; For some pecular reason, the thing we read from device 1 is ; written in device 0??? D[AR] MASK[3] COND[OBUS=0] JUMP[APRC1] C550 $ ; Jump if no PI channel. We don't want to enable arithmetic ; micro-interrupts in that case. D[AR] ROT[40] MASK[1] COND[OBUS=0] JUMP[APRC1] C550 $ ; J IF NO OV INT ENBL ; *** Don't both enables need to be checked??? D[CONST 2] ALU[DORQ] DEST[IOD] SPEC[IOB-OUT] JUMP[APRC2] NORM $; ENABLE OV INT ; Turn on arithmetic interrupts APRC1: D[CONST 2] ALU[-D&Q] DEST[IOD] SPEC[IOB-OUT] NORM $; CLR OV INT ; Turn off arithmetic interrupts APRC2: MAPF[10] CYLEN[IOB-OUT] D[AR] DEST[Q] JUMP[APRCK1] $ ; Finish turning arithmetic interrupts off or on, and we're done ;Check for clock interrupts (and other things) APRCHK: PUSHJ[APRCI] NORM $; GET CONI BITS IN AR & Q APRCK1: .REPEAT 1 - WAITS [ D[AR] MASK[3] COND[OBUS=0] JUMP[MAIN] C550 $; DONE IF PI=0 D[AR] ROT[24] MASK[1] COND[-OBUS=0] JUMP[APDINT] C550 $; J IF PDLOV INT D[AR] ROT[43] ALU[D&Q] DEST[Q] SHORT $; AND MASK WITH FLAG D[CONST 11] ROT[3] ALU[D&Q] COND[-OBUS=0] JUMP[APDINT] C550 $; J IF OV INT D[CONST 10] ROT[6] ALU[D&Q] COND[OBUS=0] JUMP[MAIN] C550 $; DONE IF NO CLOCK INT ; \ / ];.REPEAT 1 - WAITS .REPEAT WAITS [ D[AR] ROT[27.] COND[OBUS<0] SPEC[MA_PC] DEST[MA] JUMP[MAIN1] C550 $ ;If no APR interrupt is not requested, don't interrupt. ;Otherwise, fall thru ];.REPEAT WAITS ; \ / (Falls thru from APRCK1) APDINT: D[AR] MASK[3] DEST[Q AR] JUMP[PIGEN] NORM $; GET CHAN #, CAUSE INTERRUPT APRCI: ;TEMP -- LATER WE FIX OV APRCII: PUSHJ[CLKRDFLG] NORM $ ;Get CLOCK FLAG in AR 35, rest of AR = 0 .DEFINE APRGBT [R1 R2] [ D[PC] ROT[R1] MASK[1] DEST[Q] SHORT $ D[AR] ROT[R2] ALU[DORQ] DEST[AR] SHORT $ ] APRGBT[1 6] APRGBT[4 41] APRGBT[7 33] D[AR] ROT[17] DEST[Q] SHORT $; SET FLAGS .REPEAT 1 - WAITS [ D[10 + APRSTS] SPEC[A-MEM-APR] ALU[DORQ] DEST[Q AR] NORM POPJ $ ];.REPEAT 1 - WAITS .REPEAT WAITS [ ;SAIL's KA-10 has a processor modification which sets bit 27 (400 bit) if the ;APR is NOT interrupting. This feature is used in a CONSZ chain and would ;consume many instructions to simulate in a critical path in the system. D[10 + APRSTS] SPEC[A-MEM-APR] ALU[DORQ] DEST[Q AR] NORM $ ;Construct full status D[AR] MASK[3] COND[OBUS=0] JUMP[APRCIN] NORM $ ;Set 400 bit if interrupts disabled ;(This may not be the same as SAIL) D[AR] ROT[24] MASK[1] COND[-OBUS=0] POPJ C550 $ ;If pushdown overflow, we will interrupt. D[AR] ROT[43] ALU[D&Q] DEST[Q] SHORT $ ;Combine flag with enable to see which interrupts D[CONST 11] ROT[3] ALU[D&Q] COND[-OBUS=0] JUMP[APRCIY] C550 $ ;Jump if overflow is causing an interrupt. D[CONST 10] ROT[6] ALU[D&Q] COND[-OBUS=0] JUMP[APRCIY] C550 $ ;Jump if clock is causing an interrupt. APRCIN: D[CONST 4] ROT[6] DEST[Q] SHORT $ ;Not interrupting, set 400 bit in APR status APRCIY: D[AR] ALU[DORQ] DEST[AR Q] POPJ NORM $ ;Turn on 400 bit if needed. ;Note, that since we ANDed something with Q, ORing in Q is ;a NO-OP if we didn't go thru APRCIN. ];.REPEAT WAITS APRDI: MAPF[2] D[IOD] DEST[MEMSTO] COND[-MA-AC] LBJUMP[MSMAIN] CYLEN[IOB-IN] $ .PAIR UIOTRP[MUUO] $ ;Trap if not IOT-USER Mode APIOT: IOTDIS[53] ;PDLO1 PDLO2 PDLO5 PDLO3 PDLO4 PDLO6 PDLO SOED STOPS SOVRS SECCS SOEDOV PDLO1: PUSHJ[PDLO] NORM $ ;SET PDLO BIT D[PC] DEST[AR MEMSTO] NORM $ MAPF[MASTO] D[IR] MASK[18.] SPEC[CLR-HALF] DEST[PC] COND[-MA-AC] LBJUMP[MSMAIN] NORM $ PDLO2: PUSHJ[PDLO] NORM $; SET FLAG PDLO5: D[AR] DEST[MEMSTO] COND[-MA-AC] LBJUMP[MSMAIN] NORM $ PDLO3: ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[PPOP] CYLEN[FIXM] $ D[MEM] DEST[AR] PUSHJ[PDLO] NORM $ D[IR] MASK[18.] DEST[MA] JUMP[PDLO5] NORM $ PDLO4: ACSEL[MA] ALU[AC] DEST[FIXMAC-MAPF-RD] MAPF[PPOP] CYLEN[FIXM] $ PUSHJ[PDLO] NORM $ D[MEM] MASK[18.] DEST[PC] JUMP[MAIN] NORM $ ;PDLOV from ADJSP PDLO6: PUSHJ[PDLO] NORM $ JUMP[MAIN] NORM $ PDLO: D[PC] DEST[Q] SHORT $ ;Set bit 9 of PC to indicate that a PDL OV has happened... D[CONST 1] ROT[35. - 9.] ALU[DORQ] DEST[CRYOV] NORM POPJ $ ;...MAIN will notice this bit and go to PDLTRP below. PDLTRP: ;Here from MAIN when PC bit 9 is on. D[10 + APRSTS] A-MEM-APR DEST[Q AR] NORM $ ;APR CONI word to Q (leave also in AR to give PIGEN the APR PI chn) D[CONST 1] ROT[20] ALU[DORQ] A-MEM-APR&DEST-A-MEM DEST[APRSTS] NORM $ ;set PDLOV bit D[PC] DEST[Q] SHORT $ ;Now clear the pseudo-trap flag in bit 9 of PC. D[CONST 1] ROT[35. - 9.] ALU[-D&Q] DEST[CRYOV] NORM $ D[AR] MASK[3] DEST[AR] C550 -OBUS=0 JUMP[PIGEN] $ ;...and request interrupt (AR already has APR PI chn.) JUMP[MAIN] $ .USE[NORMAL] .REPEAT F3SW [ SOED: D[CONST 1] DEST[DEV-ADR] SPEC[IOB-IN] NORM $ D[IOD] MAPF[2] DEST[Q HOLD] CYLEN[IOB-IN] $ D[CONST 1] ROT[25] ALU[D&Q] COND[OBUS=0] JUMP[DOHALT] C600 $ D[PC] COND[-OBUS<0] SPEC[IOB-IN] JUMP[. + 3] C550 $; J IF NO OV D[IOD] MAPF[4] DEST[Q CLR-DEV-FROM-INTR] CYLEN[IOB-IN] $ D[CONST 2] ALU[D&Q] COND[-OBUS=0] JUMP[SOEDOV] C550 $ ;J IF OV INT EN NORM JUMP[SOEDA] $ .USE[NORMAL] SOEDA: D[10 + ECCSVP] SPEC[A-MEM-APR] MASK[4] DEST[Q] NORM $ .REPEAT 1 - XUCODE [ D[MASK 8.] ROT[4] ALU[DORQ] DEST[AR CLR-DEV-FROM-INTR] NORM SPEC[IOB-IN] $ ;;7760 IS NEW LOC. OF ERROR LOG. ];.REPEAT 1 - XUCODE .REPEAT XUCODE [ D[MASK 9.] ROT[4] ALU[DORQ] DEST[AR CLR-DEV-FROM-INTR] NORM SPEC[IOB-IN] $ ;;17760 IS NEW LOC. OF ERROR LOG. ];.REPEAT XUCODE MAPF[4] D[IOD] DEST[Q] CYLEN[IOB-IN] $ D[CONST 1] ROT[7] ALU[D&Q] COND[-OBUS=0] JUMP[.] C550 $ ALU[0] DEST[MUCODE-HI] CYLEN[MUSTO] $ D[MEM] DEST[Q] NORM $ D[MASK 42] ROT[25] ALU[D&Q] DEST[MUCODE-LO] CYLEN[MUSTO] $ D[AR] ALU[D+1] DEST[ECCSVP] SPEC[A-MEM-APR&DEST-A-MEM] NORM $ SPEC[IOB-IN] D[CONST 1] DEST[DEV-ADR] NORM $ ;NOW READ STATE OF MAP ON, OV ENBL, ETC. D[IOD] DEST[IR-ADR] MAPF[4] CYLEN[IOB-IN] $ ;PRESERVE IN IR. ALU[0] DEST[DEV-ADR] SHORT $ ;;; D[IR] ROT[31.] COND[OBUS<0] PUSHJ[ECC-UNC] C550 $ ;IF ERROR WAS UNCORRECTABLE, GO SEE ABOUT INTERRUPTING. ALU[0] DEST[IOD] SPEC[IOB-OUT] NORM $ ;PUT JUNK IN LIGHTS MAPF[2] D[MEM] SPEC[IOB-OUT] CYLEN[IOB-OUT] $ ;LTS_OBUS MAPF[10] DEST[CLR-MI-ERR] CYLEN[IOB-OUT] $; TURN OFF MAP D[MEM] DEST[MA HI-ABS-MA] NORM $; GET DATA CYLEN[C500] $;WAIT D[MEM] DEST[MEMSTO] NORM $; RE-STORE IT NORM $; WAIT -- FOR LUCK D[IR] DEST[IOD] SPEC[IOB-OUT] NORM $; RESTORE STATE OF MAP, ETC. MAPF[10] ALU[0] DEST[HI-ABS-MA] CYLEN[IOB-OUT] $; DEST[CLR-MI-ERR] JUMP[MAIN] $ ;CLEAR THE ERROR FLIPFLOP ] ;; END OF .REPEAT F3SW ;(ECC-UNC moved to bottom of page) .REPEAT F2SW [ STOPS: D[CONST 1] DEST[DEV-ADR] JUMP[DOHALT] NORM $ SOVRS: D[PC] COND[-OBUS<0] SPEC[IOB-IN] JUMP[. + 3] DEST[CLR-DEV-FROM-INTR] C550 $ ; J IF NO OV D[IOD] MAPF[4] DEST[Q CLR-DEV-FROM-INTR] CYLEN[IOB-IN] $ D[CONST 2] ALU[D&Q] COND[-OBUS=0] JUMP[SOEDOV] C550 $ ;J IF OV INT EN JUMP[.] $ ; HOW COULD WE GET HERE? .USE[AREA53] SECCS: D[CONST 1] DEST[DEV-ADR] SPEC[IOB-IN] NORM $ D[IOD] MAPF[2] DEST[Q HOLD] CYLEN[IOB-IN] $ D[10 + ECCSVP] SPEC[A-MEM-APR] MASK[4] DEST[Q] NORM $ .REPEAT 1 - XUCODE [ D[MASK 8.] ROT[4] ALU[DORQ] DEST[AR CLR-DEV-FROM-INTR] NORM SPEC[IOB-IN] $ ;;7760 IS NEW LOC. OF ERROR LOG. ];.REPEAT 1 - XUCODE .REPEAT XUCODE [ D[MASK 9.] ROT[4] ALU[DORQ] DEST[AR CLR-DEV-FROM-INTR] NORM SPEC[IOB-IN] $ ;;17760 IS NEW LOC. OF ERROR LOG. ];.REPEAT XUCODE MAPF[4] D[IOD] DEST[Q] CYLEN[IOB-IN] $ ;;;;; D[CONST 1] ROT[7] ALU[D&Q] COND[-OBUS=0] JUMP[.] C550 $ ALU[0] DEST[MUCODE-HI] CYLEN[MUSTO] $ D[MEM] DEST[Q] NORM $ D[MASK 42] ROT[25] ALU[D&Q] DEST[MUCODE-LO] CYLEN[MUSTO] $ D[AR] ALU[D+1] DEST[3] SPEC[A-MEM-APR&DEST-A-MEM] NORM $ D[CONST 1] DEST[DEV-ADR] NORM $ DEST[CLR-DEV-FROM-INTR] SPEC[IOB-IN] SHORT $ D[IOD] DEST[IR-ADR] MAPF[4] CYLEN[IOB-IN] $ ALU[0] DEST[DEV-ADR] SHORT $ ;NOTE: This conflicts with the use of the lights by diagnostics. ALU[0] DEST[IOD] SPEC[IOB-OUT] NORM $ ;PUT JUNK IN LIGHTS MAPF[2] ALU[Q] SPEC[IOB-OUT] CYLEN[IOB-OUT] $ ;LTS_OBUS MAPF[10] DEST[CLR-MI-ERR] CYLEN[IOB-OUT] $; TURN OFF MAP ALU[Q] DEST[A-MEM-ECC-DATA] DEST-A-MEM NORM $ ;Save info for reading via opcode 750. D[MEM] DEST[MA HI-ABS-MA] NORM $; GET DATA CYLEN[C500] $;WAIT D[MEM] DEST[MEMSTO] NORM $; RE-STORE IT NORM $; WAIT -- FOR LUCK D[IR] DEST[IOD] SPEC[IOB-OUT] NORM $; RESTORE STATE OF MAP, ETC. MAPF[10] ALU[0] DEST[HI-ABS-MA] CYLEN[IOB-OUT] $; DEST[CLR-MI-ERR] JUMP[MAIN] NORM $ ] ;; END OF .REPEAT F2SW SOEDOV: ALU[0] DEST[DEV-ADR] NORM $ D[CONST 2] ALU[-D&Q] DEST[IOD] SPEC[IOB-OUT] NORM $; CLR OV INT MAPF[10] CYLEN[IOB-OUT] PUSHJ[APRCII] $; GET CONI BITS D[AR] MASK[3] DEST[Q AR] JUMP[PIGEN] NORM $; DO INTR. ;$*$*$*$ No space left in NORMAL by now... .USE[OTHER] ECC-UNC: ;SEE IF WE SHOULD GIVE INTERRUPT FOR HARD ECC ERR ;RETURN TO CALLER IF NOT, BUT STILL SET PAR ERR FLAG. D[14] DEST[Q] NORM $ ;FIRST, SET PAR ERR FLAG IN PI CONI BITS. D[CONST 1] ROT[35. - 19.] ALU[DORQ] DEST[AR 4] DEST-A-MEM NORM $ D[AR] ROT[35. - 20.] C550 COND[-OBUS<0] POPJ $ ;IF PAR ERR INTRPT ENABLE OFF, DO NO MORE. D[10 + APRSTS] MASK[3] DEST[Q AR] C550 COND[OBUS=0] POPJ $ ;IF APR PI CHAN IS 0, DON'T GIVE INTRPT. DEST[CLR-MI-ERR] NORM JPOP[PIGEN] $ ;CLEAR ERR FF AND GIVE INTERRUPT ON APR CHANNEL. ;; 60 HZ CLOCK READING AND INTERRUPT ROUTINES .REPEAT OTP [ .ORG[2134] ;INTRPT LOC. FOR DEV. 5 CLKINT: NORM PUSHJ[CLRDEVINT] $ ;Enable addressing of other devices. D[CONST 1] ALU[NOTD] DEST[Q] PUSHJ[DEV6CL] NORM $ ;Clear hdwr int. enable for 60HZ clk. ] ;OTP .REPEAT NTP [ ;We branch here from CTYINT if intrpt. is really 60HZ CLK. CLKINT: START-OUT ALU[0] DEST[IOD] NORM $ ;Clear hardware int. enb. for 60HZ CLK. MAPF[6] C600 $ ] ;NTP .REPEAT TYMNET [ DEST[CLR-DEV-FROM-INTR] PUSHJ[TYMCLK] C600 $ ;Start up TYMNET interface if needed. ];TYMNET DEST[CLR-DEV-FROM-INTR] JUMP[APRCHK] C600 $ ;Cause PI on APR channel if enabled, and exit. CLKRDFLG: ;Put hardware 60HZ CLK FLAG into AR35. START-IN D[CONST 6] DEST[DEV-ADR] NORM $ ;Select device 6. MAPF[5] D[IOD] ROT[34. + 1] MASK[1] DEST[AR] CYLEN[IOB-IN] POPJ $ ;Get bit and return. .REPEAT NTP [ ;Ucode for KENNEDY or PERTEC formatter and DMA tape controller. .REPEAT 1 - TAPE [ .INSERT CFKNYD.SLO ] .REPEAT TAPE [ ;New (DMA tape controller, Pertec compatible fmtr ) .INSERT TAPE.SLO ] ] ;NTP .REPEAT KNYTAPE [ ;KENNEDY TAPE CONTROL UCODE .INSERT CFKNYP.SLO ] ;ENDX OF KENNEDY TAPE CODE .REPEAT TLXTAPE [ ;TELEX TAPE CONTROL UCODE .INSERT CFTLX.SLO ] ;ENDX OF TELEX TAPE CODE .REPEAT SLOWTAPE [ ;UCODE FOR BARE 800 BPI TAPE DRIVE .INSERT CFBARE.SLO ] ;END OF SLOW TAPE CODE .REPEAT 125TAPE [ ;UCODE FOR BARE 800 BPI, 125 IPS TAPE DRIVE .INSERT CFB125.SLO ] ;END OF SLOW 125 IPS TAPE CODE ;TAPE DISPATCH .REPEAT 1 - XUCODE [ ;If we have extended ucode memory, these are different. .OPCODE[725] ;TAPE IOTS ;725 - Obsolete version of read (no word count, E = core address.) D[CONST 7] DEST[DEV-ADR] NORM COND[-USER] LBJUMP[TAPERD] $ NOP $ ;726 - MTAPE D[CONST 7] DEST[DEV-ADR] NORM JUMP[TAPEMT] $ NOP $ ;727 - READ STATUS D[CONST 7] DEST[DEV-ADR] NORM JUMP[TAPERS] $ NOP $ ;730 - READ 1 RECORD, STORE UP TO (AC) WORDS STARTING E. D[CONST 7] DEST[DEV-ADR] NORM COND[-USER] LBJUMP[TAPENR] $ NOP $ ;731 - WRITE 1 record of E words starting from CORE LOC IN AC. D[CONST 7] DEST[DEV-ADR] NORM COND[USER] JUMP[UTAPWR] $ NORM JUMP[TAPEWR] $ ;732 - READ 1 record, store up to E words starting at (AC). D[CONST 7] DEST[DEV-ADR] NORM COND[-USER] LBJUMP[TAPERX] $ NOP $ ] ;1 - XUCODE .REPEAT XUCODE [ ;If we don't have extended ucode memory, these are different. .OPCODE[725] ;TAPE IOTS ;725 - Obsolete version of read (no word count, E = core address.) GETADR[TAPERD] JUMP[TAPDSP] $ ;726 - MTAPE GETADR[TAPEMT] JUMP[TAPDSP] $ ;727 - READ STATUS GETADR[TAPERS] JUMP[TAPDSP] $ ;730 - OBSOLETE ! --read 1 record, store up to (AC) words starting at E. GETADR[TAPENR] JUMP[TAPDSP] $ ;731 - WRITE 1 record of E words starting from CORE LOC IN AC. GETADR[TAPEWR] JUMP[TAPDSP] $ ;732 - READ 1 record, store up to E words starting at (AC). GETADR[TAPERX] JUMP[TAPDSP] $ ] ;XUCODE .RELOC TAPDSP: D[CONST 7] DEST[DEV-ADR] COND[-USER] JUMP[GOHIGH] $ ;Load device code for tape, test for user mode. UIOTRP[MUUO] $ ;In user mode-- trap unless IOT USER GOHIGH: ;Jump into high part of umemory, using 12-bit addr. in Q D[CONST (XUCODE * 10) + 2] ROT[9.] ALU[D+1] C600 SDISP $ ;This takes us to loc. 2001 and pre-sets the 10000 bit. .ORG[2001] D[CONST XUCODE] ROT[12.] ALU[DORQ] SDISP $ ;This finally takes us to loc. 10000+[Q] .RELOC .REPEAT XUCODE [ .USE[HIGHMEM] $ ] .PAIR HIGHSMAIN: D[MEM] ACSEL[MA] DEST[AC] NORM JUMP[GOMAIN] $ NORM JUMP[GOMAIN] $ GOMAIN: GETADR[MAIN] $ ;Do extended mode jump to MAIN. GOLOW: ;Jump to loc. in lower 4K indicated by contents of Q. .REPEAT XUCODE [ ALU[0] C600 SDISP $ ;This goes to loc. 10000 and pre-clears the 10000 bit. .ORG[10000] ] ;XUCODE C600 ALU[Q] SDISP $ ;Now we actually go to low u-mem. .USE[OTHER] ;------------------------------------------------------------------------------ ; ; FooVision ; ;------------------------------------------------------------------------------ .REPEAT VID [ .INSERT VID.SLO ];VID .OPCODE[766] .REPEAT ((1 - VID) * (773 - 766 + 1)) [ ILGIOT $ ;OPS 766:773 NOP $ ];1-VID .REPEAT VID [ ILGIOT $ ;OP 766 = illegal (reserved) NOP $ GETADR[VIDDPA] JUMP[GOHIGH]$ ;OP 767 = DPYADD ;Note: GETADR expands to 2 words FIXM2$ ;OP 770 = VIDIN D[CONST 36] DEST[DEV-ADR] JUMP[VIDIN]$ FIXM1$ ;OP 771 = VIDOUT D[CONST 36] DEST[DEV-ADR] JUMP[VIDOUT]$ GETADR[VIDDPI] JUMP[GOHIGH]$ ;OP 772 = DPYINI ;Note: GETADR expands to 2 words GETADR[VIDDPO] JUMP[GOHIGH]$ ;OP 773 = DPYOUT ;Note: GETADR expands to 2 words ];VID .RELOC ;FLOATING POINT, KA10 STYLE. ;NONDISPATCH CODE. .DEFINE CFPLOW[] [D[AR] ACSEL[AC+1] DEST[AC] JUMP[FPLOW] NORM ] .DEFINE JINSEXP[] [D[AR] ROT[27.] DEST[Q] JUMP[INSEX1] NORM ] .DEFINE CINSEXP[] [D[AR] ROT[27.] DEST[Q] PUSHJ[INSEX1] NORM ] .DEFINE CFDS[] [D[MEM] ALU[D#AC] DEST[AR] PUSHJ[FDS1] NORM] ;***** DON'T USE A-MEM 0 FOR ANYTHING BESIDES DISPATCHES!!! TVR-Sep80 ***** ;***** This must be fixed!!!! TVR-Sep80 ***** UFA1: ALU[AC] DEST[0 AR] DEST-A-MEM PUSHJ[FADSUB] NORM $ D[10] DEST[AR O_AC] SHORT $ D[AR] ACSEL[AC+1] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] $ .PAIR ;: 6460 ;.PAIR DFN1: ALU[NOTAC] DEST[AC] JUMP[. + 2] NORM $ ALU[0-AC] DEST[AC] SHORT $ D[MEM] DEST[Q] SHORT $ D[MASK 9] ROT[27.] ALU[D&Q] DEST[Q] SHORT $ D[AR] MASK[27.] ALU[DORQ] DEST[MEMSTO] MEMSTMA $ FSCZAP: ALU[0] DEST[MA AC] SPEC[MA_PC] JUMP[MAIN1] NORM $ FSC1: D[AR] MASK[9] ROT[9] DEST[Q AR] SHORT $ D[MASK 8] ROT[27.] ALU[-D&AC] DEST[AC] COND[-OBUS<0] JUMP[FSC2] C550 $ D[MASK 9] ALU[D#Q] DEST[Q AR] SHORT $ D[MASK 8] ROT[27.] ALU[DORAC] DEST[AC] SHORT $ FSC2: D[MA] MASK[18.] ALU[D+Q] DEST[IR-ADR] SHORT $ ALU[0] DEST[Q] PUSHJ[NRMLIZ] NORM $ CINSEXP $ SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ FAOS1: FAOS5: ALU[AC] DEST[AR] PUSHJ[FADSUB] NORM $ DEST[MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ FAOS2: ALU[AC] DEST[AR] PUSHJ[FADSUB] NORM $ CFPLOW $ FAOS3: ALU[AC] DEST[AR] NORM $ D[CONST 11] DEST[DEV-ADR] SHORT $ ALU[AC] DEST[0] DEST-A-MEM PUSHJ[FADSUB] NORM $ D[10] DEST[MEMSTO O_AC] MEMST $ FAOS4: ALU[AC] DEST[AR] PUSHJ[FADSUB] NORM $ ALU[AC] DEST[MEMSTO] MEMST $ FMP1: FMP5: ALU[AC] DEST[AR] PUSHJ[FM] NORM $ SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ FMP2: ALU[AC] DEST[AR] PUSHJ[FM] NORM $ CFPLOW $ FMP3: ALU[AC] DEST[AR] NORM $ D[CONST 11] DEST[DEV-ADR] SHORT $ ALU[AC] DEST-A-MEM PUSHJ[FM] DEST[0] NORM $ D[10] DEST[MEMSTO O_AC] MEMST $ FMP4: ALU[AC] DEST[AR] PUSHJ[FM] NORM $ ALU[AC] DEST[MEMSTO] MEMST $ ;Macro to test for divide by zero .DEFINE DIVTST[] [D[MEM] MASK[27.] COND[OBUS=0] JUMP[FPNDIV] C550] ;;;FD5: D[MA] ROT[18.] DEST[HOLD] SPEC[LEFT] NORM $ ;Not needed. TVR-Apr80 ;FDV,FDVR FD1: DIVTST $ ;Check for divide by zero CFDS $ SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ ;------------------------------------------------------------------------------ ;LONG MODE FLOATING DIVIDE. ;------------------------------------------------------------------------------ FD2: DIVTST $ ;AR.0,IR.35:=XOR(DIVIDEND SIGN,DIVISOR SIGN). D[MEM] ALU[D#AC] DEST[AR] SHORT $ D[AR] MASK[1] ROT[1] DEST[IR-ADR] SHORT $ ;Flush sign & exponent from Dividend Low D[MASK 27.] ALU[D&AC] ACSEL[AC+1] DEST[AR] SHORT $ D[AR] ROT[9] DEST[AC] ACSEL[AC+1] SHORT $ ;Positive form of Dividend to AC, AR; original form to AMEM[1] ALU[AC] DEST[AR 1] DEST-A-MEM COND[-OBUS<0] JUMP[FD2A] CYLEN[C450] $ ALU[0-AC] ACSEL[AC+1] DEST[AC] COND[OBUS=0] JUMP[. + 2] C550 $ ALU[NOTAC] DEST[AC AR] JUMP[. + 2] SHORT $ ALU[0-AC] DEST[AC AR] NORM $ FD2A: D[CONST 1] ROT[27.] ALU[AC+D] DEST[AR] NORM $ ;Add 1 to exp. of dividend, since we will do only a 27-bit divide. ALU[AC] ACSEL[AC+1] DEST[6] DEST-A-MEM NORM $ ;Put low-order mantissa in AMEM[6] for FD. D[CONST 27.] LLOAD NORM $ ;Do only a 27-bit divide, so remainder will come out right. PUSHJ[FD] NORM $ ;Perform the divide (returns: AC=quotient, AMEM[6]=remainder) ;AC+1 gets 0 if remainder = 0. D[16] ACSEL[AC+1] DEST[AC] COND[OBUS=0] JUMP[FD2D] C550 $ ;Calculate exponent of remainder. D[11] DEST[Q] C550 -OBUS<0 JUMP[. + 3] $ ;Check sign of dividend, jump if positive. ALU[0-Q] DEST[1] DEST-A-MEM NORM $ ;Negate the dividend (so the exponent will be in pos. form) ACSEL[AC+1] ALU[0-AC] DEST[AC] NORM $ ;Negate the remainder. D[11] ROT[9.] MASK[8] DEST[Q] NORM $ ;Recover exp. of dividend. ;A-MEM[7] has (dividend HOW)-(divisor). D[17] COND[-OBUS<0] JUMP[. + 2] C550 $ D[CONST 1] ALU[Q-D] DEST[Q] SHORT $ D[CONST 26.] ALU[Q-D] DEST[Q] COND[OBUS18] JUMP[FD2C] C600 $ ;Jump if exponent underflow. .DEFINE SWAPAC[] [ ;Interchange (AC) and (AC+1) ALU[AC] ACSEL[AC+1] DEST[AR] SHORT $ D[AR] DEST[AR O_AC] SHORT $ D[AR] ACSEL[AC+1] DEST[AC] SHORT $ ] ;SWAP QUOTIENT (AC) AND REMAINDER (AC+1) SWAPAC ;INSERT EXPONENT INTO REMAINDER. ALU[Q] DEST[AR] PUSHJ[INSEXP] NORM $ SWAPAC FD2D: SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ FD2C: ALU[0] ACSEL[AC+1] DEST[AC MA] SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ FD3: DIVTST $ ALU[AC] DEST[0] DEST-A-MEM PUSHJ[FDS] NORM $ D[10] DEST[MEMSTO O_AC] MEMST $ FD4: DIVTST $ CFDS $ ALU[AC] DEST[MEMSTO] MEMST $ ;HERE ON DIVISOR=0. SET NO DIVIDE, OVF,FLOV,RETURN. FPNDIV: D[PC] DEST[Q] SHORT $ D[CONST 1] ROT[23.] ALU[DORQ] DEST[Q] PUSHJ[SETFOV] NORM $ DEST[MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;------------------------------------------------------------------------------ ;NORMALIZE DOUBLE PRECISION NUMBER IN AC,Q WHOSE EXPONENT ; IS IN IR-ADR. LEAVE EXPONENT IN AR, NORMALIZED NUMBER IN AC,Q. ; IF NUMBER IS 0, LEAVE 0 IN AR,AC, AND Q. ;------------------------------------------------------------------------------ .DEFINE CNORM[] [D[AR] DEST[AC] PUSHJ[NRMLIZ] NORM] ;A. Return immediately if 0. NRMLIZ: ALU[QORAC] DEST[AR] COND[OBUS=0] POPJ C550 $ ;B. Check for mantissa overflow, move exponent to AR. ALU[AC] DEST[AR] PUSHJ[NORMOV] NORM $ ;Check mantissa and shift right if necessary D[IR] MASK[18.] COND[-OBUS=0] POPJ C550 $ ;If we adjusted right, then we definitely don't have to ;shift left. We're done here. ;C. Left shift until normalized. ALU[AC] COND[OBUS<0] JUMP[NEGNOR] CYLEN[C450] $ ;Separate into two cases, positive and negative POSNOR: D[CONST 1] ROT[26.] ALU[D&AC] COND[-OBUS=0] POPJ C550 $ ;If high order bit of mantissa is one, we're done D[AR] ALU[D-1] DEST[AR] SHORT $ ;Decrement the exponent ALU[SH-AC] MASK[2] DEST[D6] JUMP[POSNOR] NORM $ ;Shift left and try again. NEGNOR: D[CONST 1] ROT[26.] ALU[D&AC] COND[OBUS=0] JUMP[NN1] C550 $ ;If high order bit of mantissa is zero, we're done D[AR] ALU[D-1] DEST[AR] SHORT $ ;Decrement the exponent ALU[SH-AC] MASK[2] DEST[D6] JUMP[NEGNOR] NORM $ ;Shift left and try again. NN1: D[MASK 27.] ALU[D&AC] COND[-OBUS=0] POPJ C550 $ ;Check for case of exactly -(2^n). If it isn't, we're done D[CONST 1] ROT[26.] ALU[DORAC] DEST[AC] SHORT $ ;We went one too far, backup by simply OR'ing in the relevant ;bit in the same manner as shifting would. ;(*** What about Q?? TVR-Jul80) D[AR] ALU[D+1] DEST[AR] POPJ NORM $ ;Increment exponent to account for simulated left shift. ;------------------------------------------------------------------------------ ;CHECK FOR MANTISSA OVERFLOW INTO EXPONENT FIELD. CALL WITH ; AR&AC,Q: # TO NORMALIZE, IR-ADR: ITS EXPONENT. ; LEAVE EXPONENT IN AR. SET IR-ADR=0 IF NO OVERFLOW. SET IR-ADR<>0 ; IF OVERFLOW, AND NORMALIZE. ; ;M.O. <=> [AR0<>AR8] OR [(AR8=1) AND (AR9-35=0)] ;------------------------------------------------------------------------------ NORMOV: D[AR] ROT[8] ALU[D#AC] COND[OBUS<0] JUMP[NOVYES] C550 $ ;Check to make sure AR<0>=AR<8>. If they don't, the mantissa ;clearly overlaps the exponent field. D[MASK 27.] ALU[D&AC] COND[-OBUS=0] JUMP[NOVNO] C550 $ ;Check for AR<9:35> for zero. If not zero, we're OK D[CONST 1] ROT[27.] ALU[D&AC] COND[OBUS=0] JUMP[NOVNO] C550 $ ;Check AR<8>. If zero, we're OK ; \ / ;Mantissa has overflowed, adjust it. Right by one should be enough. NOVYES: ALU[SH-AC] MASK[1] DEST[D4] SHORT $ ;Shift mantissa right (i think?) D[IR] MASK[18.] ALU[D+1] DEST[AR IR-ADR] POPJ NORM $ ;Increment mantissa and flag that we changed it by setting ;IR<18:35> to be non-zero. ;Mantissa has not overflowed. NOVNO: D[IR] MASK[18.] DEST[AR] SHORT $ ;Save exponent in AR ALU[0] DEST[IR-ADR] POPJ NORM $ ;Zero IR<18:35> to signify success ;------------------------------------------------------------------------------ ;INSERT EXPONENT IN AR INTO WORD IN AC. ;SET FLOV,FLUN,OVF FLAGS AS REQUIRED. ;PRESERVES AR, CLOBBERS Q. ;------------------------------------------------------------------------------ INSEXP: D[AR] ROT[27.] DEST[Q] NORM $ ;Move exponent into position INSEX1: D[MASK 8.] ROT[27.] ALU[D&Q] DEST[Q] SHORT $ ;Flush stuff in mantissa area ALU[Q#AC] DEST[AC] SHORT $ ;Fill in exponent (complementing it if (AC) is negative !) D[AR] COND[OBUS18] JUMP[EXPUF] C550 $ ;Check for underflow (i.e. below range of exponent offset) D[AR] MASK[10.] ROT[28.] COND[OBUS=0] POPJ C550 $ ;Check for overflow (i.e. above range of exponent offset) D[PC] DEST[Q] SHORT $ ;Setup to set floating overflow SETFOV: D[CONST 11] ROT[32.] ALU[DORQ] DEST[CRYOV] POPJ NORM $ ;Turn on overflow and floating overflow EXPUF: D[PC] DEST[Q] SHORT $ ;Setup to set no divide and floating overflow D[CONST 1] ROT[24.] ALU[DORQ] DEST[Q] JUMP[SETFOV] NORM$ ;Turn on no divide, then do overflows ;------------------------------------------------------------------------------ ;FLOATING ADD AC&AR TO MEM. RESULT, NORMALIZED AND ROUNDED ; IF REQUIRED IN AC,Q. ;------------------------------------------------------------------------------ .DEFINE BLEXPS[DES1 TIME DES2] [ D[MASK 8] ROT[27.] ALU[DORAC] DEST[DES2] COND[OBUS<0] JUMP[. + 2] C550 $ D[MASK 8] ROT[27.] ALU[-D&AC] DEST[DES2] SHORT $ D[MEM] DEST[Q] COND[OBUS<0] JUMP[. + 2] C550 $ D[MASK 8] ROT[27.] ALU[-D&Q] DEST[DES1] JUMP[. + 2] NORM $ D[MASK 8] ROT[27.] ALU[DORQ] DEST[DES1] CYLEN[TIME] $ ];BLEXPS ;A. + FORM EXPONENT OF AC,MEM RTO AR,Q RESP. FADSUB: D[AR] MASK[9] ROT[9] DEST[Q AR] SHORT $ FADSU1: D[CONST 1] ROT[8] ALU[D&Q] COND[OBUS=0] JUMP[FS1] C550 $ D[MASK 9] ALU[D#Q] DEST[AR] SHORT $ FS1: D[MEM] MASK[9] ROT[9] DEST[Q] SHORT $ D[CONST 1] ROT[8] ALU[D&Q] COND[OBUS=0] JUMP[FS2] C550 $ D[MASK 9] ALU[D#Q] DEST[Q] SHORT $ ;B. COMPUTE DIFFERENCE, SWAP OPRANDS IF AC HAS LARGER EXP. ; LEAVE + DIFFERENCE IN Q, DIFF -1 IN LOOP CTR. ; LEAVE LARGER EXPONENT IN IR-ADR. FS2: ALU[Q] DEST[IR-ADR] SHORT $ D[AR] ALU[Q-D] DEST[Q] COND[-OBUS<0] JUMP[FS3] C600 $ D[AR] DEST[IR-ADR] SHORT $ D[MEM] DEST[HOLD O_AC] NORM $ ALU[0-Q] DEST[Q] NORM $ FS3: ALU[Q-1] DEST[AR] LLOAD NORM $ ;C. BLANK EXPONENTS. BLEXPS[HOLD NORM AC] ;D. IF DELTA EXPONENTS >62., AC GOES TO OBLIVION. D[AR] ALU[D+1] DEST[Q] COND[OBUS=0] JUMP[FS5] C600 $ D[CONST 63.] ALU[Q-D] COND[OBUS<0] JUMP[FS4] C600 $ ALU[0] DEST[AC] SHORT $ ALU[0] DEST[Q] JUMP[FS5] NORM $ FS4: ALU[0] DEST[Q] SHORT $ ALU[SH-AC] DEST[D4] MASK[1] LOOP [.] NORM $ ;E. ADD. FS5: D[MEM] ALU[D+AC] DEST[AR] SHORT $ ;F. NORMALIZE RESULT. D[IR] DEST[AC] SHORT $ ;CHECK FOR UFA D[CONST 1] ROT[40] ALU[D&AC] COND[OBUS=0] JUMP[UFANOR] C550 $ ;------------------------------------------------------------------------------ ;ENTER HERE WITH RESULT IN AR,Q, EXP IN IR-ADR. ;------------------------------------------------------------------------------ FPNAR: CNORM $ ;NOPE, NORMALIZE ;(Calls NRMLIZ which changes register usage from above and adjusts various ;things. "LEAVE EXPONENT IN AR, NORMALIZED NUMBER IN AC,Q.") ;G. ROUND IF NECESSARY, INSERT EXPONENT INTO HIGH ORDER WORD OF RESULT. ALU[Q] COND[-OBUS<0] DEST[HOLD] JUMP[NORND] CYLEN[C450] $ ;Save Q in HOLD (i.e. MEM) ;If Q<0> is zero, don't round D[IR] DEST[Q] NORM $ ;Get Q so we check bit meaning rounding (??? Can't this be ;done with D[IR] ROT[7] COND[OBUS<0]... ???) D[CONST 1] ROT[35] ALU[D&Q] COND[OBUS=0] JUMP[NORND] C550 $ ;Check opcode to see if rounding is requested. ;If not, we're done D[MEM] DEST[Q] SHORT $ ;Restore Q D[MASK 43] ALU[D&Q] COND[-OBUS=0] JUMP[YESRND] C550 $ ;Round if Q<1:35> is non-zero (? what does this signify???) ALU[AC] COND[OBUS<0] JUMP[INSEXP] CYLEN[C450] $ ;If mantissa is negative, we don't round (???) ; \ / YESRND: D[AR] DEST[IR-ADR] SHORT $ ;Setup IR for NRMLIZ ALU[AC+1] DEST[AC] PUSHJ[NRMLIZ] NORM $ ;Increment high order word and normalize once more (???) JINSEXP $ ;Now stick in exponent ; --- NORND: D[MEM] DEST[Q] JUMP[INSEXP] NORM $ ;Restore Q and insert exponent(?) ;UFA NORMALIZATION -- ONLY ON MANTISSA OVERFLOW. UFANOR: D[AR] ALU[DORQ] DEST[AC] COND[OBUS=0] POPJ C600 $ D[AR] DEST[AC] PUSHJ[NORMOV] NORM $ JINSEXP $ ; --- ;------------------------------------------------------------------------------ ;SETUP LOW ORDER FP RESULT, STORE BOTH IN AC,AC+1 ;ENTER WITH LOW WORD IN MEM, HIGH WORD IN AC, HIGH ;WORD'S EXPONENT IN AR&AC+1. ;------------------------------------------------------------------------------ FPLOW: D[CONST 27.] ACSEL[AC+1] ALU[AC-D] DEST[AC AR] SHORT $ D[CONST 1] ROT[7] ACSEL[AC+1] ALU[D&AC] COND[-OBUS=0] JUMP[ZLOW] C550 $ D[MEM] ROT[27.] MASK[27.] DEST[Q] COND[OBUS=0] JUMP[ZLOW] C550 $ D[AR] ROT[27.] ACSEL[AC+1] DEST[AC] SHORT $ D[MASK 8] ROT[27.] ALU[D&AC] ACSEL[AC+1] DEST[AC] SHORT $ ACSEL[AC+1] ALU[QORAC] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ZLOW: ACSEL[AC+1] ALU[0] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;------------------------------------------------------------------------------ ; ; FLOATING MULTIPLY. AC&AR BY MEM. ; ;*** This code produces non-zero results if MEM=-1.0 and AC=0 !!! TVR-Jun80 ;------------------------------------------------------------------------------ ;A. SUM OF + FORM EXPONENTS -128.+1 TO IR-ADR. +1 BECAUSE 28 ; STEPS ARE USED TO PROVIDE ONE GUARD DIGIT. FM: D[AR] MASK[9] ROT[9] DEST[Q AR] NORM$ ;Extract the exponent from AC (which was copied into AR) D[CONST 1] ROT[8] ALU[D&Q] COND[OBUS=0] JUMP[FM1] C550 $ ;Check sign bit of number. Nothing special if positive D[MASK 9] ALU[D#Q] DEST[AR] SHORT $ ;Sign is negative, we want the one-complement of the exponent ;field to get the actual exponent. FM1: D[MEM] MASK[9] ROT[9] DEST[Q] SHORT $ ;Extract the exponent from MEM D[CONST 1] ROT[8] ALU[D&Q] COND[OBUS=0] JUMP[FM2] C550 $ ;Check sign bit of number. Nothing special if positive D[MASK 9] ALU[D#Q] DEST[Q] SHORT $ ;Sign is negative, we want the one-complement of the exponent ;field to get the actual exponent. FM2: D[AR] ALU[D+Q] CARRY DEST[Q] SHORT $ ;Add the two exponents ;+1. FOR GUARD DIGIT. D[CONST 1] ROT[7] ALU[Q-D] DEST[IR-ADR] SHORT $ ;Account for exponent bias. Put exponent in a safe place. ;B. BLANK EXPONENTS. BLEXPS[Q SHORT AR] ;Extend the sign to blank out the exponent field. We will ;now have perfectly good integers here, of 27 bit magnitude ;(assuming that the numbers were normalized to begin with). ALU[0] DEST[AC] PUSHJ[TESMUL] NORM $ ;28. STEPS. ;;; ALU[Q] DEST[AR] SHORT $ ;FLUSH SIGN IN LO WD. D[MASK 7] ALU[-D&Q] DEST[Q AR] SHORT $ ;FLUSH SIGN IN LO WD. ;Flush remenants of multiplier in low order part of ;word. MASK field determined empirically (35-28???) D[AR] ALU[D+Q] DEST[Q] SHORT $ ;Make low order word unsigned. ALU[AC] DEST[AR] JUMP[FPNAR] NORM $ ;28. STEP INTEGER MULTIPLY FOR USE BY FM. TESMUL: D[CONST 27.] LLOAD NORM $ ;LOOP 28 TIMES JUMP[DOMUL1] NORM $ ;TEST. ;------------------------------------------------------------------------------ ;SHORT STYLE FLOATING DIVIDE AC BY MEM. ; XOR OF DIVISOR&DIVIDEND SIGNS IN AR BIT 0. ;------------------------------------------------------------------------------ FDS: D[MEM] ALU[D#AC] DEST[AR] SHORT $ FDS1: D[AR] MASK[1] ROT[1] DEST[IR-ADR] SHORT $ ALU[AC] DEST[AR] COND[-OBUS<0] JUMP[. + 2] C550 $ ALU[0-AC] DEST[AC AR] SHORT $ ALU[0] DEST[6] DEST-A-MEM NORM $ D[CONST 28.] LLOAD NORM $ ;Do only a 28-bit divide. ;------------------------------------------------------------------------------ ; Floating Divide ; ; DIVIDEND HIGH ORDER WORD IN AR, LOW IN A-MEM[6]. DIVISOR IN MEM. ; BOTH IN POSITIVE FORM. IR.35=XOR(DIVIDEND SIGN,DIVISOR SIGN). ;------------------------------------------------------------------------------ FD: ;A. PUT DIVISOR IN + FORM, GET DIVISOR EXPONENT. ;.1 Shuffle IR.35 into A-MEM[4]. D[IR] MASK[18.] DEST[4] DEST-A-MEM NORM $ ;Save IR-ADR in A-MEM D[MEM] DEST[Q] COND[-OBUS<0] JUMP[. + 2] C550 $ ;Check for negative divisor D[MEM] ALU[0-D] DEST[Q HOLD] NORM $ ;Negate divisor D[MEM] ROT[9] MASK[8] DEST[IR-ADR] NORM $ ;Extract exponent from divisor, store in IR<18:35> D[MASK 8] ROT[27.] ALU[-D&Q] DEST[HOLD] NORM $ ;Extract mantissa from divisor ;B. Fetch and blank HOW Dividend exponent. D[AR] ROT[9] MASK[8] DEST[Q] NORM $ ;Extract dividend exponent. D[AR] MASK[27.] DEST[AC] SHORT $ ;Extract mantissa from dividend ;C. Compute resultant exponent. D[IR] MASK[18.] ALU[Q-D] DEST[Q] SHORT $ ;Subtract divisor exponent from dividend exponent D[CONST 1] ROT[7] ALU[D+Q] DEST[IR-ADR] NORM $ ;Include exponent offset ;D. Move LOW Dividend to Q. D[16] DEST[Q] SHORT $ ;E. If divisor<=dividend, shift dividend right, increment the ; resultant exponent. save diff. in A-MEM[7] for long mode. D[MEM] ALU[AC-D] DEST[7] DEST-A-MEM COND[-OBUS<0] JUMP[FDAD] C600 $ ;F. Save exp in A-MEM[5] FDSHFT: D[IR] DEST[5] DEST-A-MEM NORM $ PUSHJ[DODIV4] NORM $ ;Do the divide. Result DOES NOT have signs adjusted. ;G. Save remainder in A-MEM[6], put quotient in AC, AR; put 0 in Q. ALU[AC] DEST[6] DEST-A-MEM NORM $ ALU[Q] DEST[AC AR] SHORT $ ALU[0] DEST[Q] SHORT $ ;H. Prepare to round 28. bit result. ALU[SH-AC] MASK[1] DEST[D4] SHORT $ ;Shift AC,Q rt 1 bit D[15] ALU[D-1] DEST[IR-ADR] NORM PUSHJ[FPNAR] $ ;Move exp for FPNAR, normalize and insert exponent into quotient. D[14] MASK[1] C550 OBUS=0 POPJ $ ;Done if positive result. ALU[0-AC] DEST[AC] NORM POPJ $ ;Negate quotient. ;------------------------------------------------------------------------------ ;HERE WHEN DIVIDEND IS >= DIVISOR. SHIFT DIVIDEND RIGHT ; AND INCREMENT RESULTANT AC. THIS WILL ALLOW DIVIDE TO ; SUCCEED IF BOTH DIVISOR & DIVIDEND WERE NORMALIZED ; AND DIVISOR <> 0. ;------------------------------------------------------------------------------ FDAD: ALU[SH-AC] MASK[2] DEST[D4] SHORT $ D[IR] MASK[18.] ALU[D+1] DEST[IR-ADR] JUMP[FDSHFT] NORM $ ;ADJSP1 ADJSP2 DMOVE2 DMOVN2 DMOVM2 DMVNM2 DMVNM3 DMVNM4 DMVNM5 KAFIXP KAFIXN FIXR1 KIFIX1 FIXRN KIFIXN FIXER FIXER1 FIXER2 FIXER3 ; ;Strays from KI instructions ; .REPEAT XUCODE [ .USE[AREA50] ;Squeeze this stuff into the space vacated by MBOOT. ] ;(ADJSP continued) ;Left result is negative. Check right side. ADJSP1: D[IR] MASK[22] ALU[D+AC] DEST[AR] NORM $ ;Add right half D[MASK 22] ALU[-D&Q] DEST[Q] SHORT $ ;Isolate left half D[AR] MASK[22] ALU[DORQ] DEST[O_AC AR] NORM $ ;Merge halves and store D[IR] COND[-OBUS18] SPEC[MA_PC] DEST[MA] JUMP[MAIN1] C550 $ ;If E was positive, it wasn't an overflow (just a bad idea) ;Start fetching next instruction D[AR] COND[OBUS<0] JUMP[MAIN] C550 $ ;If original was negative, we're OK. Start doing next ;instruction if no sign changed in left half JUMP[PDLO6] NORM $ ;ADJSP got a PDLOV ;ADJSP left result positive ADJSP2: D[MASK 22] ALU[-D&Q] DEST[Q] SHORT $ ;Isolate left half D[AR] MASK[22] ALU[DORQ] DEST[O_AC AR] $ ;Merge halves and store D[IR] COND[OBUS18] SPEC[MA_PC] DEST[MA] C550 $ ;If E was negative, it wasn't an overflow (just a bad idea) ;Start fetching next instruction D[AR] COND[-OBUS<0] JUMP[MAIN1] C550 $ ;If original was positive, we're OK. Start doing next ;instruction if no sign changed in left half JUMP[PDLO6] NORM $ ;ADJSP got a PDLOV ;(DMOVE continued) DMOVE2: D[MA] ALU[D+1] DEST[MA] NORM $ ;Fetch second word FIXM1 $ ;Complete fetch ACSEL[AC+1] D[MEM] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] CYLEN[FIXM+1] $ ;Put it in the second AC and start next instruction ;(DMOVN continued) DMOVN2: D[MA] ALU[D+1] DEST[MA] NORM $ ;Fetch second word FIXM1 $ ;Complete fetch ACSEL[AC+1] D[MEM] ALU[0-D] DEST[AC MA] SPEC[MA_PC] CYLEN[FIXM+1] $ ;Negate low order word and put it in the second AC ;Start next instruction fetch (Note that DEST[MA] is ;really associated with SPEC[MA_PC]) ;*** Is FIXM+1 really the right thing??? ACSEL[AC+1] D[MASK 1] ROT[35.] ALU[-D&AC] DEST[AC] COND[-OBUS=0] JUMP[MAIN1] NORM $ ;Clear stupid bit 0. ;If the low order part is non-zero, we're done ACSEL[AC] ALU[AC+1] DEST[AC] SPEC[CRYOV] JUMP[MAIN1] C550 $ ;Increment high order word and we're finally done. ;(DMOVEM continued) .PAIR DMOVM2: CYLEN[MEMSTO] ACSEL[AC] D[MEM] DEST[AC] NORM $ ;Write it also in the AC CYLEN[MEMSTO] D[MA] ALU[D+1] DEST[MA] $ ;Setup to write second word ACSEL[AC+1] ALU[AC] DEST[MEMSTO] MEMST $ ;Write secord word. ;(DMOVNM continued) DMVNM2: ACSEL[AC+1] ALU[0-AC] DEST[Q] SHORT $ ;Negate low order word. ACSEL[AC+1] D[MASK 1] ROT[35.] ALU[-D&Q] DEST[Q] COND[-OBUS=0] JUMP[DMVNM4] NORM $ ;Clear stupid bit 0. ;If the low order part is non-zero, no change needed to ;high order word. D[AR] ALU[AC+1] DEST[AR STRT-WRT] SPEC[CRYOV] COND[-MA-AC] JUMP[DMVNM5] NORM $ ;Increment high order word and start first store DMVNM3: ACSEL[MA] D[MEM] DEST[AC] JUMP[DMVNM5] $ ;Store is to an AC, write into 2901. DMVNM4: DEST[STRT-WRT] COND[MA-AC] JUMP[DMVNM3] $ ;Start first store. Jump if to an AC DMVNM5: D[MA] ALU[D+1] DEST[MA] NORM $ ;Finish write. Note that due to FIXM2, we don't have to ;worry about map faults. ;Prepare for secord write ALU[Q] DEST[MEMSTO] MEMST $ ;Do final write (low order word into (E+1)) ;KAFIX (Opcode 247) continued ;Positive number to fix KAFIXP: D[IR] ROT[27.] MASK[9.] DEST[Q] COND[-OBUS=0] PUSHJ[FIXER] $ ;Extract exponent adjustment factor and do fixing ACSEL[AC] ALU[Q] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;Put result into AC and we're done ;Negative number to fix KAFIXN: D[IR] ROT[27.] MASK[9.] DEST[Q] COND[-OBUS=0] PUSHJ[FIXER] $ ;Extract exponent adjustment factor and do fixing ;;; ACSEL[AC] D[MASK R] ALU[D/#Q] DEST[AC MA] ;*** Assembler loses! ACSEL[AC] D[2] MASK[R] ALU[D/#Q] DEST[AC MA] ;Sigh... SPEC[MA_PC] JUMP[MAIN1] NORM $ ;Put sign extended result into AC and we're done ;(FIXR continued) FIXR1: D[MEM] COND[OBUS<0] JUMP[FIXRN] C550 $ ;Round different directions D[CONST 20] ROT[30.] ALU[D+Q] DEST[AC AR] PUSHJ[FADSUB] NORM $ ;Positive. Finish making constant 0.5 and add it D[CONST 33] DEST[Q] SHORT $ ;Start making magic constant ALU[AC] DEST[AR HOLD] JUMP[FIXR2] NORM $ ;Setup for FIXER. Rest is same as KIFIX ; --- FIXRN: D[CONST 60] ROT[30.] ALU[D-Q] DEST[AC AR] PUSHJ[FADSUB] NORM $ ;Negative. Finish making constant -0.5 and add it D[CONST 33] DEST[Q] SHORT $ ;Start making magic constant D[CONST 2] ROT[6] ALU[DORQ] DEST[Q] SHORT $ ;Finish making magic constant ALU[0-AC] DEST[AR HOLD] PUSHJ[FIXER] NORM $ ;Setup for FIXER ACSEL[AC] ALU[0-Q] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;Negate it back again and start next instruction ; --- ;(KIFIX continued) KIFIX1: D[MEM] DEST[AR] COND[OBUS<0] JUMP[KIFIXN] C550 $ ;Load up things for FIXER, check for positive mantissa FIXR2: D[CONST 2] ROT[6] ALU[DORQ] DEST[Q] PUSHJ[FIXER] NORM $ ;Finish making magic constant and do fix. ACSEL[AC] ALU[Q] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;Put result into AC and we're done ; --- ; --- KIFIXN: D[CONST 2] ROT[6] ALU[DORQ] DEST[Q] SHORT $ ;Finish making magic constant D[MEM] ALU[0-D] DEST[HOLD AR] PUSHJ[FIXER] NORM $ ;ABS to both MEM and AR. Fix the number ACSEL[AC] ALU[0-Q] DEST[AC MA] SPEC[MA_PC] JUMP[MAIN1] NORM $ ;Negate it back again and start next instruction ;Fix a number (without sign extension) in MEM, AR=ABS(MEM), Q=magic number ;(233 for normal fix) FIXER: D[AR] ROT[9] MASK[9] ALU[D-Q] DEST[ROTR Q] COND[OBUS<0] JUMP[FIXER2] C550 $ ;Calculate number of positions to move ;Jump if we'll be shifting right (n<2^26) D[CONST 27.] ALU[D+Q] DEST[MASKR] NORM $ ;Construct appropriate mask D[MEM] MASK[27.] DEST[HOLD] NORM $ ;Flush exponent, our mask won't reach. D[CONST 9.] ALU[Q-D] COND[OBUS<0] JUMP[FIXER1] C550 $ ;Check for overflow ;;; Set overflow here. What kind? (We can live without it for KAFIX, since it ;;; never did check, but when KIFIX is done, this will have to be corrected.) D[CONST 1] ROT[35.] ALU[Q] PUSHJ[QORCRY] NORM $ ;Set overflow flag. D[CONST 44] DEST[MASKR] NORM $ ;For those losers who want to see some of the number... ;Now that we know how much to shift things, do it and return. FIXER1: D[MEM] ROT[R] MASK[R] DEST[Q] NORM POPJ $ ;Gee, that was fast. ;Negative, shift count, the easy case. FIXER2: D[CONST 27.] ALU[D+Q] DEST[MASKR] COND[OBUS<0] JUMP[FIXER3] $ ;Construct appropriate mask. If !x!<1, return zero D[CONST 36.] ALU[D+Q] DEST[ROTR] JUMP[FIXER1] NORM $ ;Hardware doesn't believe in negative shift counts ;Number is fractional, i.e. shift would go off the end. Return zero FIXER3: ALU[0] DEST[Q MASKR] SHORT POPJ $ ;Just return zero. Set mask just in case .REPEAT XUCODE [ .USE[OTHER] ] ;FLTR, continued FLTR1: D[CONST 33] DEST[Q] SHORT $ D[CONST 2] ROT[6] ALU[DORQ] DEST[IR-ADR] NORM $ ;Make magic constant for exponent ALU[0] DEST[Q] PUSHJ[FPNAR] $ ;Clear low order word ;Normalize and round (happens to have same bit on as FxxR) ;Result goes to AC SPEC[MA_PC] DEST[MA] JUMP[MAIN1] NORM $ ;Start next instruction fetch .REPEAT WK [ .INSERT WK.SLO ] ;;; Device 6 service assembled regardless of whether Tymnet, DR-11, ;;; or neither is being supported. ;;; Define subdevices of the CFT board for the TYMNET interface ;;; The first two, if written, reset the interrupt requests. .REPEAT OTP [ TNODIFS = 2 ;OUTPUT DONE INTERRUPT FF SUBSEL = REQ B TNIRIFS = 4 ;INPUT READY INTERRUPT FF SUBSEL = REQ A. TYM.LD = 1 ;MAPF value for loading output register. TYM.RD = 0 ;MAPF value for reading input register. ] ;OTP .REPEAT NTP [ TNODIFS = 17 ;OUTPUT DONE INTERRUPT FF SUBSEL = REQ B TNIRIFS = 16 ;INPUT READY INTERRUPT FF SUBSEL = REQ A. TYM.LD = 15 ;MAPF value for loading output register. TYM.RD = 5 ;MAPF value for reading input register. ] ;NTP ;;; Location 2141 is where device 6 interrupts come. TYMFOO = . .ORG[2141] ;Prepare to call MAPOFF by re-loading DEV-ADR. D[CONST 1] DEST[DEV-ADR] NORM JUMP[TNI] $ .USE[TYMFOO] .REPEAT 1 - TYMNET - DR11P [ TNI: DEST[CLR-DEV-FROM-INTR] JUMP[MAIN] $ ;"It can't happen here" ];1 - TYMNET - DR11P ;;; Device 6 control register hacking. ;;; Register 1 in device 6's A memory contains the state of the ;;; control register, since we can't read it back. ;;; Q contains mask for bits not to be changed. Remaining bits are cleared. ;;; On return, Q has new value of output register and AR is zeroed. DEV6CL: ALU[0] DEST[AR] NORM JUMP[DEV6ST] $ ;;; Q contains mask for bits not to be changed. ;;; Remaining bits are loaded from AR. ;;; On return, Q has new value of output register. DEV6ST: D[CONST 6] DEST[DEV-ADR] NORM $ ;;; Enter here if device address already set up to 6. DEV6ST1: D[11] ALU[D&Q] DEST[Q] NORM $ ;Get AMEM(1), mask it. DEV6ST2: D[AR] ALU[DORQ] DEST[Q IOD] SPEC[IOB-OUT] NORM $ ;Or in new data MAPF[TYM.LD] ALU[Q] DEST[1] DEST-A-MEM CYLEN[IOB-OUT] POPJ $ .REPEAT TYMNET [ .INSERT TYMNET.SLO ];TYMNET .REPEAT DR11P [ .INSERT DR11.SLO ];DR11P ; SOMETHING IS REALLY FUCKED WITH THIS ASSEMBLER, CAUSING ; THE .USE, .RELOC, AND SO FORTH MACROS NOT TO WORK. ; EVIDENTLY THE PREVIOUS PERSON TO EDIT THE MICROCODE ; HAD PROBLEMS WITH THIS TOO. MAYBE THIS WILL REMOVE THE SYMPTOM. BULLSHIT = . .USE[BULLSHIT] ;INTERVAL TIMER CODE. ;a-mem useage: ; 0 dispatch addr for interrupts ; 1 pi chn (33: 35) and intrpt waiting flag (32) ; (BITS 0,19 ARE ON FOR USE BY TAPE CODE) ; 2 CONSTANT W/ ONLY BIT 19 ON (USED BY TAPE CODE) ; 3 INTERVAL TIMER REGISTER. .REPEAT OTP [ TIM.CLR.ROT = 35. - 6 TIM.DO = 1 TIM.DI = 1 TIM.ENB = 1 TIM.DEV = 7 TIM.LOC = 2150 ] ;OTP .REPEAT NTP [ TIM.CLR.ROT = 0 TIM.DO = 11 TIM.DI = 1 TIM.ENB = 10 TIM.DEV = 5 TIM.LOC = 2134 ] ;NTP .ORG[TIM.LOC] ;$*$*$ INTRPTS FROM DEVICE COME HERE. .REPEAT 1 - TIMER [ DEST[CLR-DEV-FROM-INTR] JUMP[MAIN] $ ;FLUSH DEV INTERRUPTS ] .REPEAT TIMER [ NORM JUMP[TIMINT] $ ] .RELOC TIMINT: ;ALL DEV 5 INTS COME FROM INTERVAL TIMER... START-OUT D[CONST 1] ROT[TIM.CLR.ROT] DEST[IOD] NORM $ ;Clear the TIMER OVERFLOW FLAG. MAPF[TIM.ENB] D[13] DEST[Q] C800 $ ;Get TIMER REGISTER. D[CONST 1] ROT[12.] ALU[D+Q] DEST[Q 3] DEST-A-MEM C550 COND[-CRY0] JUMP[MAIN] $ ;Increment the count by 2^12, exit if no overflow. D[11] MASK[3] DEST[AR] C550 COND[OBUS=0] JUMP[MAIN] $ ;Timer overflowed. ignore if no PI CHANNEL assigned. D[11] DEST[Q] NORM $ ;Get full contents of A-MEM[1]. D[CONST 10] ALU[DORQ] DEST[1] DEST-A-MEM NORM JUMP[PIGEN] $ ;Set the "interrupting" status bit and generate a PI. .OPCODE[760] ;TIMER PSEUDO-IOT DISPATCH TABLE ENTRIES. ; TCONO -- 760 D[CONST TIM.DEV] DEST[DEV-ADR] SHORT $ D[11] DEST[Q] NORM JUMP[TCNO1]$ ; TCONI -- 761 D[CONST TIM.DEV] DEST[DEV-ADR] NORM PUSHJ[TCNI1] $ ;get bits. D[AR] DEST[MEMSTO] MEMST $ ;store them and return. ; TCONSO -- 762 D[CONST TIM.DEV] DEST[DEV-ADR] NORM PUSHJ[TCNI1] $ ;get bits. D[MASK 22] ALU[D&Q] C550 COND[-OBUS=0] LBJUMP[DSKP1] $ ;Skip if on. ; TCONSZ -- 763 D[CONST TIM.DEV] DEST[DEV-ADR] NORM PUSHJ[TCNI1] $ ;get bits. D[MASK 22] ALU[D&Q] C550 COND[OBUS=0] LBJUMP[DSKP1] $ ;Skip if off. ; TDATAO -- 764 LOAD THE 36-BIT TIMER D[CONST TIM.DEV] DEST[DEV-ADR] NORM $ FIXM1 JUMP[TDATO] $ ; TDATAI -- 765 READ TIMER REGISTER START-IN D[CONST TIM.DEV] DEST[DEV-ADR] NORM PUSHJ[TDTI] $ ;get bits. D[AR] DEST[MEMSTO] MEMST $ ;Store them and return. .RELOC TCNO1: D[MASK 32.] ROT[4] ALU[D&Q] DEST[Q] NORM $ D[IR] MASK[3] ALU[DORQ] DEST[1] DEST-A-MEM JUMP[MAIN] $ ;Put new PI CHAN. in bits 33-35 of A-MEM[1]. TCNI1: D[11] MASK[4] DEST[Q AR] NORM $ ;get intrpt flag and pi chn D[IR] ALU[D&Q] DEST[Q] NORM POPJ $ ;this is for conso, z TDATO: D[MEM] MASK[12.] DEST[Q] NORM $ ;Get low 12 bits of new timer value... START-OUT D[CONST 1] ROT[35. - 7] ALU[DORQ] DEST[IOD] NORM $ ;Place in hardware counter (the "TP TIMER"). MAPF[TIM.DO] D[MASK 24.] ROT[12.] DEST[Q] C800 $ D[MEM] ALU[D&Q] DEST[3] DEST-A-MEM NORM JUMP[MAIN] $ ;Put other 24 bits into A-MEM[3] (the "TIMER REGISTER"). TDTI: MAPF[TIM.DI] START-IN D[IOD] ROT[12.] MASK[12.] DEST[AR] C600 $ ;Read hardware timer. MAPF[TIM.DI] D[IOD] ROT[12.] MASK[12.] DEST[Q] C600 $ ;Read it again. START-IN D[AR] ALU[D#Q] C550 COND[-OBUS=0] JUMP[TDTI] $ ;If it changed, try again (to ensure that we don't get a garbaged ; value because of reading it while it is changing). D[13] ALU[DORQ] DEST[AR] NORM POPJ $ ;Combine high-order bits from A-MEM[3] with ; low-order bits from hardware counter. ; IMP,VID,PAN,GRN,DLS,LPT,VC etc. ;------------------------------------------------------------------------------ ; ; Packet Switching Network Interface (IMP) ; ;------------------------------------------------------------------------------ .REPEAT IMP [ .REPEAT 1 - IMP1 [ ; ;Insert main code body here .INSERT IMP.SLO ] ; 1 - IMP1 .REPEAT IMP1 [ ;Insert main code body here .INSERT IMP1.SLO ];IMP1 ];IMP ;------------------------------------------------------------------------------ ; ; Panofsky-Samson Interface ; ;------------------------------------------------------------------------------ .REPEAT STANSW [ .INSERT PAN.SLO .INSERT TMPGRN.SLO ;Temporary Grinnell Interface ];.REPEAT STANSW ;------------------------------------------------------------------------------ ; ; Data Line Scanner (TTY scanner) ; ;------------------------------------------------------------------------------ .REPEAT DLS [ .DEFINE ASRC[ X ] [D[10 + X]] .DEFINE ADEST[ X ] [DEST[X] DEST-A-MEM] .REPEAT DLS2 [ .INSERT DLS.SLO .REPEAT DLSDEB [ .INSERT DLSDEB.SLO ];DLSDEB ] ;DLS2 .REPEAT 1 - DLS2 [ .INSERT ODLS.SLO .REPEAT DLSDEB [ .INSERT ODLSDE.SLO ] ;DLSDEB ] ;1 - DLS2 ];DLS 9 JAN 80 BO ;------------------------------------------------------------------------------ ; ; Line Printer Interface (LPT) ; ;------------------------------------------------------------------------------ .REPEAT LPT [ .INSERT LPTX.SLO ];LPT ;------------------------------------------------------------------------------ ; ; Versatec Interface (VC) ; ;------------------------------------------------------------------------------ .REPEAT VC [ .INSERT VC.SLO ] ; dsk stuff ;a-mem useage: ; 0 dispatch addr for interrupts ; 1 pi chn (33: 35) and intrpt waiting flag (32) ; 2 copy of last cmd sent to controller (by opcode 721) .OPCODE[740] ;disk pseudo-iot dispatch table entries. ; dcono -- 740 d[const 10] dest[dev-adr] short $ d[ir] mask[3] dest[1] DEST-A-MEM norm jump[dcno1]$ ; dconi -- 741 d[const 10] dest[dev-adr] norm pushj[dcni1] $ ;get bits. d[ar] dest[memsto] memst $ ;store them and return. ; dconso -- 742 d[const 10] dest[dev-adr] norm pushj[dcni1] $ ;get bits. d[mask 22] alu[d&q] c550 cond[-obus=0] lbjump[dskp1] $ ; dconsz -- 743 d[const 10] dest[dev-adr] norm pushj[dcni1] $ ;get bits. d[mask 22] alu[d&q] c550 cond[obus=0] lbjump[dskp1] $ .RELOC dcno1: d[ir] mask[3] c500 cond[obus=0] jump[main] $ ; if assigned pi channel is not 0, then ; enable interrupt on "not active", by ; re-loading last cmd with 10 bit on. D[CONST 20] DEST[Q] NORM $ D[IR] ALU[D&Q] C550 OBUS=0 JUMP[DCNO2] $ D[CONST 40] DEST[Q] NORM JUMP[DCNO3] $ DCNO2: d[const 10] dest[q] short $ DCNO3: d[12] alu[dorq] dest[iod] spec[iob-out] norm $ mapf[4] cylen[iob-out] jump[main] $ dcni1: d[11] dest[q ar] norm $ ;get intrpt flag and pi chn d[ir] alu[d&q] dest[q] norm popj $ ;this is for conso, z .ORG[2156] ;$*$*$ ;interrupts from disk (dev 10) come here. D[CONST 50] ALU[NOTD] DEST[Q] NORM JUMP[DSKINT] $ .RELOC .PAIR ;$*$*$ This exists elsewhere by another name. TVR-Apr80 dskp1: jump[main] norm $ ;conso and consz lbjump to here. doskip $ dskint: d[12] ALU[D&Q] dest[iod] spec[iob-out] norm $ ;clear interrrupt enable bit (amem[2] has last cmd) mapf[4] d[11] dest[q ar] c550 cond[obus=0] jump[ddis] $ d[const 10] alu[dorq] dest[1] DEST-A-MEM norm jump[pigen] $ ;set flag and request intrpt. ddis: dest[clr-dev-from-intr] norm jump[main] $ DSKWT1: D[CONST 10] DEST[DEV-ADR AR] NORM JUMP[DSKWT4] $ DSKWT3: D[MEM] ROT[31.] C550 COND[OBUS<0] JUMP[DSKWDN] $ D[CONST 1] ROT[6] LLOAD NORM $ C550 LOOP[.] $ DSKWT4: START-IN NORM $ MAPF[0] D[IOD] DEST[HOLD] C800 JUMP[DSKWT3] $ DSKWDN: D[AR] ALU[D-1] DEST[AR] C550 COND[-OBUS=0] JUMP[DSKWT4] $ JUMP[MAIN] $ ; ;ECC logging area ; .REPEAT 1 - XUCODE [ : 7760 ];.REPEAT 1 - XUCODE .REPEAT XUCODE [ : 17760 ];.REPEAT XUCODE .REPEAT 20 [NOP $ ] ;; this should be after everything else : 0 JUMP[MSTART] $ ;Auto-load micro code tapes someday.